日期:2014-05-16 浏览次数:20789 次
Linux字符设备驱动结构
1.1 cdev结构体
在Linux2.6 内核中,使用cdev结构体来描述一个字符设备,cdev结构体的定义如下:
struct cdev {
struct kobject kobj;
struct module *owner; /*通常为THIS_MODULE*/
struct file_operations *ops; /*在cdev_init()这个函数里面与cdev结构联系起来*/
struct list_head list;
dev_t dev; /*设备号*/
unsigned int count;
};
cdev 结构体的dev_t 成员定义了设备号,为32位,其中12位是主设备号,20位是次设备号,我们只需使用二个简单的宏就可以从dev_t 中获取主设备号和次设备号:
MAJOR(dev_t dev)
MINOR(dev_t dev)
相反地,可以通过主次设备号来生成dev_t:
MKDEV(int major,int minor)
1.2 Linux 2.6内核提供一组函数用于操作cdev 结构体:
1:void cdev_init(struct cdev*,struct file_operations *);
2:struct cdev *cdev_alloc(void);
3:int cdev_add(struct cdev *,dev_t,unsigned);
4:void cdev_del(struct cdev *);
其中(1)用于初始化cdev结构体,并建立cdev与file_operations 之间的连接。(2)用于动态分配一个cdev结构,(3)向内核注册一个cdev结构,(4)向内核注销一个cdev结构
1.3 Linux 2.6内核分配和释放设备号
在调用cdev_add()函数向系统注册字符设备之前,首先应向系统申请设备号,有二种方法申请设备号,一种是静态申请设备号:
5:int register_chrdev_region(dev_t from,unsigned count,const char *name)
另一种是动态申请设备号:
6:int alloc_chrdev_region(dev_t *dev,unsigned baseminor,unsigned count,const char *name);
其中,静态申请是已知起始设备号的情况,如先使用cat /proc/devices 命令查得哪个设备号未事先使用(不推荐使用静态申请);动态申请是由系统自动分配,只需设置major = 0即可。
相反地,在调用cdev_del()函数从系统中注销字符设备之后,应该向系统申请释放原先申请的设备号,使用:
7:void unregister_chrdev_region(dev_t from,unsigned count);
1.4 cdev结构的file_operations结构体
这个结构体是字符设备当中最重要的结构体之一,file_operations 结构体中的成员函数指针是字符设备驱动程序设计的主体内容,这些函数实际上在应用程序进行Linux 的 open()、read()、write()、close()、seek()、ioctl()等系统调用时最终被调用。在include/linux/fs.h文件中定义,这里不一一详解,仅仅解析一些常用的API。
struct file_operations {
/*拥有该结构的模块计数,一般为THIS_MODULE*/
struct module *owner;<