在前面的一片文章中贴出了一个scull的简单驱动。
通常而言 主设备号标示设备对应的驱动程序,次设备正确确定设备文件所指的设备。(次设备号还是不大清楚) 我觉得,按我的理解,主设备号用来标示一个驱动程序。而次设备号则是你的驱动程序/模块来标示的,可以根据不同的次设备号来执行不同的代码或者是驱动不同的设备。
设备号由结构体dev_t表示,它和主设备号,次设备号之间的转换如下
分配设备号的方法有两种,一种是动态获取。一种是固态定义。
当一个设备号分配成功后,使用cat /proc/devices便可以看到您分配到的主设备号和设备名称
【贴出结果】
一个驱动模块被应用程序调用的过程如下图所示:
应用程序如同访问一般的文件一样访问设备,将设备当成一个文件来操作。因此需要一套完整的接口来衔接驱动模块和应用程序,这就是
file_operations (包含在<linux/fs.h>
file_operations是linux中最重要的一个结构体,其成员基本上都是函数指针,这和windows中的回调函数有点类似。为驱动层提供一个驱动接口。
列举一下file_operations的成员:
file_operations{
struct mode* owner;
ssize_t (*read)
ssize_t (*write)
int (*ioctl)
int (*release)
.............
}
每一个设备相当如一个设备文件,因此也有file结构体,file结构代表一个打开的文件,它由内核open的时候创建,并传递给在该文件上进行操作的所有函数。直到最后的close函数,在文件的所有实例都被关闭之后,内核会释放这个数据结构。
字符设备的注册:
老的注册方法:
int register_chrdev(unsigned int major,const char* name,struct file_operations *f_ops);
注销驱动:
int unregister_chrdev(unsigned int major,const char*name);
在linux内核中,驱动用struct cdev结构体来表示,包含在<linux/cdev.h> 中
注册一个结构体可以使用: