您的位置:首页 > 运维架构 > Linux

linux字符cdev和Inode的关系

2014-02-26 20:09 183 查看
  struct mutex *lock;  }; 

static struct char_device_struct { 

  struct char_device_struct *next; 

  unsigned int major; 

  unsigned int baseminor; 

  int minorct; 

  char name[64]; 

  struct file_operations *fops; 

  struct cdev *cdev;                /* will die */ 

} *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; 

#define CHRDEV_MAJOR_HASH_SIZE        255 

下面本文通过一下三个方面以及他们的关联来描述字符设备驱动: 

1. 字符驱动模型 

2. 字符设备的设备号 

3. 文件系统中对字符设备文件的访问  

字符驱动模型 

  每个字符驱动由一个 cdev 结构来表示. 

  在设备驱动模型(device driver model)中, 使用 (kobject mapping domain) 来记录字符设备驱动.这是由 struct kobj_map 结构来表示的. 它内嵌了255个struct probe指针数组,kobj_map由全局变量cdev_map引用:  

static struct kobj_map *cdev_map; 

 相关函数说明: 

  cdev_alloc() 用来创建一个cdev的对象 

  cdev_add() 用来将cdev对象添加到驱动模型中,其主要是通过kobj_map()来实现的. 

  kobj_map() 会创建一个probe对象,然后将其插入cdev_map中的某一项中(这里的某一项是如何确定的,是否是按照设备的主设备号呢?),并关联probe->data 指向 cdev 

  struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index),根据设备号,在cdev_map中查找其cdev对象内嵌的kobject. (probe->data->kobj),返回的是cdev的kobject(此函数是在打开设备文件是调用到的,在注册字符设备时不用) 

字符设备的设备号 

  字符设备的主,次设备号的分配: 

  全局数组 chrdevs 包含了255(CHRDEV_MAJOR_HASH_SIZE 的值)个 struct char_device_struct的元素. 

  每一个对应一个相应的主设备号. 

  如果分配了一个设备号,就会创建一个 struct char_device_struct 的对象,并将其添加到 chrdevs 中. 

  这样,通过chrdevs数组,我们就可以知道分配了哪些设备号. 

    

 

 

相关函数: 

  register_chrdev_region( ) 分配指定的设备号范围 

  alloc_chrdev_region( ) 动态分配设备范围 

  他们都主要是通过调用函数__register_chrdev_region() 来实现的 

  要注意,这两个函数仅仅是注册设备号! 如果要和cdev关联起来,还要调用cdev_add() 

  register_chrdev( ) 申请指定的设备号,并且将其注册到字符设备驱动模型中. 

  它所做的事情为: 

  1. 注册设备号, 通过调用 __register_chrdev_region() 来实现 

  2. 分配一个cdev, 通过调用 cdev_alloc() 来实现 

  3. 将cdev添加到驱动模型中, 这一步将设备号和驱动关联了起来. 通过调用 cdev_add() 来实现 

  4. 将第一步中创建的 struct char_device_struct 对象的 cdev 指向第二步中分配的cdev. 由于register_chrdev()是老的接口,这一步在新的接口中并不需要. 

文件系统中对字符设备文件的访问 

对于一个字符设备文件, 其inode->i_cdev 指向字符驱动对象cdev, 如果i_cdev为 NULL ,则说明该设备文件没有被打开. 

由于多个设备可以共用同一个驱动程序.所以,通过字符设备的inode 中的i_devices 和 cdev中的list组成一个链表 

 

 

 首先,系统调用open打开一个字符设备的时候, 通过一系列调用,最终会执行到 chrdev_open. 

  (最终是通过调用到def_chr_fops中的.open, 而def_chr_fops.open = chrdev_open. 这一系列的调用过程,本文暂不讨论)

  int chrdev_open(struct inode * inode, struct file * filp) 

  chrdev_open()所做的事情可以概括如下: 

  1. 根据设备号(inode->i_rdev), 在字符设备驱动模型中查找对应的驱动程序, 这通过kobj_lookup() 来实现, kobj_lookup()会返回对应驱动程序cdev的kobject. 

  2. 设置inode->i_cdev , 指向找到的cdev. 

  3. 将inode添加到cdev->list的链表中. 

  4. 使用cdev的ops 设置file对象的f_op 

  5. 如果ops中定义了open方法,则调用该open方法 

  6. 返回. 

  执行完 chrdev_open()之后,file对象的f_op指向cdev的ops,因而之后对设备进行的read, write等操作,就会执行cdev的相应操作.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  驱动 linux cdev