字符设备驱动 架构分析

34 篇文章 0 订阅

转贴:http://www.chinaunix.net/jh/4/1027719.html

字符串驱动的初始化流程大体如下:
static int __init mydriver_init(void) //驱动程序的初始化
{  

   ……
    MYDRIVER_Major = register_chrdev(0, DEVICE_NAME, &mydriver_fops); //向内核注册一个设备,返回值为注册的主设备号
    if (MYDRIVER_Major < 0)
    {
        printk(DEVICE_NAME " can't register major number/n");
        return MYDRIVER_Major;
    }
    ……
    mydriver_class = class_create(THIS_MODULE, DEVICE_NAME); 
//注册一个类,使mdev可以在"/dev/"目录下 面建立设备节点
    ……
    //创建一个设备节点,节点名为DEVICE_NAME
    device_create(mydriver_class, NULL, MKDEV(MYDRIVER_Major, 0), NULL, DEVICE_NAME);
    ……
}

相关数据结构: 

struct cdev { 

struct kobject kobj; 

struct module *owner; 

const struct file_operations *ops; 

struct list_head list; 

dev_t dev; 

unsigned int count; 

}; 
struct kobj_map { 

struct probe { 

struct probe *next; 

dev_t dev; 

unsigned long range; 

struct module *owner; 

kobj_probe_t *get; 

int (*lock)(dev_t, void *); 

void *data; 

} *probes[255]; 

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. 文件系统中对字符设备文件的访问 

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

[attach]212944[/attach] 

相关函数说明: 

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 
  
2. 字符设备的设备号 

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

全局数组 chrdevs 包含了255(CHRDEV_MAJOR_HASH_SIZE 的值)个 struct char_device_struct的元素. 每一个对应一个相应的主设备号. 

如果分配了一个设备号,就会创建一个 struct char_device_struct 的对象,并将其添加到 chrdevs 中. 这样,通过chrdevs数组,我们就可以知道分配了哪些设备号. 

[attach]212945[/attach] 

相关函数:  
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()是老的接口,这一步在新的接口中并不需要. 

 //************************************************

int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);

    其中,major是为设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态地分配一个主设备号。name是设备名。fops就是前面所说的对各个调用的入口点的说明。此函数返回0表示成功。返回-EINVAL表示申请的主设备号非法,一般来说是主设备号大于系统所允许的最大设备号。返回-EBUSY表示所申请的主设备号正在被其它设备驱动程序使用。如果是动态分配主设备号成功,此函数将返回所分配的主设备号。如果register_chrdev操作成功,设备名就会出现在/proc/devices文件里。

    在成功的向系统注册了设备驱动程序后(调用register_chrdev()成功后),就可以用mknod命令来把设备映射为一个特别文件,其它程序使用这个设备的时候,只要对此特别文件进行操作就行了。

//**************************************************

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

对于一个字符设备文件, 其inode->i_cdev 指向字符驱动对象cdev, 如果i_cdev为 NULL ,则说明该设备文件没有被打开. 
由于多个设备可以共用同一个驱动程序.所以,通过字符设备的inode 中的i_devices 和 cdev中的list组成一个链表 

[attach]212946[/attach] 

首先,系统调用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的相应操作.

 device_create分析 http://blog.chinaunix.net/space.php?uid=23373524&do=blog&id=2426966

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值