本文共 2261 字,大约阅读时间需要 7 分钟。
一、Linux驱动程序开发步骤
1.查看原理图,数据手册等
2.找相近的驱动程序作为模板
3.实现驱动程序的初始化
4.设计所要实现的操作:open,read,write,close
5.实现中断(可以不需要)
6.用insmod命令加载驱动
二、驱动框架
驱动是无法直接识别应用程序上的应用层API:read,open,write等,需要对应驱动程序上的led_read,led_open,led_write,这些都是驱动函数。
每个系统调用,驱动程序怎样和它对应起来?
使用file_operations结构,和应用层API对接。
Linux怎么知道去调用哪个驱动程序的file_operations?
根据设备类型和主设备号,需要将注册函数将主设备号和file_operations一起注册到内核
将驱动程序加载到内核,调用驱动初始化函数,像内核注册
module_init(memdev_init);
三、驱动程序的加载和卸载
module_init(memdev_init);
module_exit(memdev_exit);
四、几种重要的数据结构
struct file
file结构代表一个打开的文件,它由内核在open时创建,并传递给该文件上进行操作的所有函数,直到最后的close函数。
file结构private_data是跨系统调用时保存状态信息非常有用的资源。
file结构的f_ops 保存了文件的当前读写位置。
struct inode
内核用inode代表一个磁盘上的文件,它和file结构不同,后者表示打开的文件描述符。对于单个文件,可能会有许多个表示打开文件的文件描述符file结构,但他们都指单个inode结构。inode的dev_t i_rdev成员包含了真正的设备编号,struct cdev *i_cdev包含了指向struct cdev结构的指针。
struct file_operations
file_operations结构保存了字符设备驱动程序的方法。它是一个在 <linux/fs.h> 中定义的 struct file_operations 结构,这是一个内核结构,不会出现在用户空间的程序中,它定义了常见文件 I/O 函数的入口。系统调用函数通过内核,最终调用对应的 struct file_operations 结构的接口函数(例如,open() 文件操作是通过调用对应文件的file_operations 结构的 open 函数接口而被实现)。当然,每个设备的驱动程序不一定要实现其中所有的函数操作,若不需要定义实现时,则只需将其设为 NULL 即可。
驱动程序的简单模板:
#include设备号和设备类的创建和销毁:#include MODULE_LICENSE("GPL");//模块开源许可声明/* 模块加载时的初始化函数 */// __init的意思是将代码放入特定的初始化内存区域,初始化后空间可以回收static int __init myinit(void){ printk(KERN_CRIT"hello mymodule!\n"); printk(KERN_CRIT"module name :%s\n",THIS_MODULE->name); return 0;//内核编程,有返回值的一定不要遗漏}module_init(myinit);//告知系统哪个是初始化函数/* 模块清理函数 *///__exit的意思是如果以后不卸载则不要放入系统static void __exit myexit(void){ printk(KERN_CRIT"goodbye cruel world\n");}module_exit(myexit);//告知系统哪个是清理函数
#include#include #include //设备号注册相关#include //class和device相关MODULE_LICENSE("GPL");dev_t devno;//设备号struct class *cls; //设备类static int __init myinit(void){//在模块初始化时,动态申请前设备号 alloc_chrdev_region(&devno,10,1,"mydev"); cls=class_create(THIS_MODULE,"myclass");//创建类 device_create(cls,NULL,devno,NULL,"mynewdev");//在类下面创建设备 printk("major is %d, minor is %d\n",MAJOR(devno),MINOR(devno)); return 0;}module_init(myinit);static void __exit myexit(void){//模块清理的时候,反注册设备号 device_destroy(cls,devno);//销毁设备 class_destroy(cls);//销毁类 unregister_chrdev_region(devno,1);//反注册设备号}module_exit(myexit);
转载地址:http://kflab.baihongyu.com/