Linux字符设备驱动框架


一、设备注册(fs/char_dev.c

register_chrdev_region   ->  

__register_chrdev_region  ->  

主要任务:

struct char_device_struct类型的全局变量chrdevs[255]中倒着找到第一个可用的char_device_struct结构,将设备号和设备名等相关信息填充进去。 

 

二、设备结构分配(fs/char_dev.c

cdev_alloc  ->  通过struct cdev *p = kzalloc() 实现cdev结构的分配

 

cdev_init   ->  cdev->ops = fops;

 

cdev_add   ->

cdev_add里,调用了kobj_map()这个设备模块映射函数,将dev_t设备号加入到了kobj_map结构体里。其实就是将设备号(最大为255)放入到了一个排好序的数组里,如下代码中的

  1. struct probe *probes[255];。  
  2.   
  3. struct kobj_map {  
  4.   
  5.          struct probe {  
  6.   
  7.                    struct probe *next;  
  8.   
  9.                    dev_t dev;  
  10.   
  11.                    unsigned long range;  
  12.   
  13.                    struct module *owner;  
  14.   
  15.                    kobj_probe_t *get;  
  16.   
  17.                    int (*lock)(dev_t, void *);  
  18.   
  19.                    void *data;  
  20.   
  21.          } *probes[255];  
  22.   
  23.          struct mutex *lock;  
  24.   
  25. };  

三、设备驱动的打开

当字符设备文件通过open系统调用打开时,VFS会调用chrdev_open

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

chrdev_open主要完成以下工作:

1.         利用传递过来的inode结构里的i_rdev设备号,通过kobj_lookup找到当前设备对应的kobj对象

drivers/base/map.c

  1. struct kobject *kobj_lookup (struct kobj_map *domain, dev_t dev, int *index)  

2.         通过container_of找到kobj所在的cdev结构(注册字符设备时分配上面第二步)

3.         cdev结构中的ops(操作函数指针)赋值给file结构(传递回去让用户空间访问)。

4.         调用ops中的open(注册字符驱动时的open操作函数),实现对驱动的open访问。

相关内容