日期:2014-05-16  浏览次数:20789 次

Linux设备驱动开发详解总结(一)之字符设备驱动结构

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;<