Linux字符设备驱动结构

Linux字符设备驱动结构:

1.cdev 结构体  linux内核中使用cdev结构体来描述一个字符设备

Struct  cdev {

Struct  kobject  kobj

Struct  module *owner

Struct  file_operations  *ops; /*文件操作结构体*/

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)。。。。。。使用宏MKDEVint  major, int  minor生成主设备号;

cdev结构体中定义的了一个重要的成员 file_operations 定义了字符设备提供给虚拟文件系统的接口函数。

Linux2.6内核提供了一组函数用于操作cdev结构体:

Void  cdev_init struct  cdev  *, struct  file_operations *);

Void  cdev_add(struct  cdev  *dev_t , unsigned);

Void  cdev_del (struct  cdev *); 

 

Cdev_init 函数用于初始化cdev成员,建立cdevfile_operations之间的联系;

Cdev_addcdev_del函数分别是向系统添加和删除一个cdev(字符设备),完成字符设备的注册和注销。对cdev_add函数的调用通常发生在字符设备驱动模块的加载函数中,相反,cdev_del函数发生在字符设备驱动模块的卸载模块函数中。

Cdev_add()函数分配设备号:在调用cdev_add()函数向系统注册设备号号,应该调用register_chrdev_region()或者alloc_chrdev_region()函数向系统申请设备号。。。        Register_chrdev_regiondev_t  fromunsigned  countconst  char  *name);

相反:在调用cdev_del()函数从系统注销字符设备之后,unregister_chrdev_region()应该在被调用以释放原先申请的设备号;

Unsigned_chrdev_regiondev_t , number_of_dev);

 

file_operations 结构体

File_operations结构中的成员函数是字符设备驱动与内核的接口,字符设备驱动程序的主题内容,这些函数实际上会在应用程序进行linuxopenreadwrite等系统调用时被调用;

Struct  file_operations {

Struct  module *owner; 

/*拥有结构体的模块指针,一般为THIS_MODULES*/

Ssize_t  (read *)(struct  file *,  ,, ,,);

}

Read()函数用来想设备中读取数据,成功时返回读取的字节数,出错时返回一个负数;

Ioctl() 提供设备相关的控制命令的实现,成功返回一个非负值;

Mmap()函数将设备内存映射到进程内存中,如果设备驱动未实现此函数,用户进行mmap()系统调用时将获得 -ENODEV返回值。这个函数对于帧缓冲等设备特别有意义??。

 

ioctl()命令

字符类型

序列号

方向

数据尺寸

8bit

8bit

2bit

13/14bit

命令码的设备类型字段为一个“幻数”,可以是0~0xff之间的值,

命令码的序列号为8位宽;

命令码的方向字段为2位宽,该字段表示数据传送的方向,可能的值为_IOC_NONE(无数据传输) , _IOC_READ(读),  _IOC_WRITE(写),  _IOC_READ | _IOC_WRITE(双向);

命令码的数据长度字段,这个成员的宽度依赖与体系结构

#define  _IO (type,  nsize)  这个宏的作用是根据传入的type(设备类型字段),和nr (序列号字段)和宏隐含的方向字段移位生成命令码。。。。。

原文地址:https://www.cnblogs.com/zhou2011/p/2379174.html