免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 24313 | 回复: 17

字符设备驱动 架构分析 [复制链接]

论坛徽章:
0
发表于 2008-08-26 15:45 |显示全部楼层
好长时间没怎么看书了,最近把字符设备驱动部分又复习了一下,写个笔记.


Char Device Driver

相关数据结构:

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;


kobj_map.gif

相关函数说明:

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数组,我们就可以知道分配了哪些设备号.

char_device_struct.gif

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




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

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

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

cdev_file.gif

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

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
发表于 2008-08-26 15:49 |显示全部楼层

回复 #1 xpl 的帖子

不错,和ldd3有异曲同工之处

论坛徽章:
0
发表于 2008-08-26 15:58 |显示全部楼层
我想问问这个图是怎么画的??我记得以前好像谁问过,但是想不起来了,图画得好看:)
好帖,谢谢

[ 本帖最后由 hongmy525 于 2008-8-26 16:00 编辑 ]

论坛徽章:
0
发表于 2008-08-26 18:09 |显示全部楼层
原帖由 hongmy525 于 2008-8-26 15:58 发表
我想问问这个图是怎么画的??我记得以前好像谁问过,但是想不起来了,图画得好看:)
好帖,谢谢


ascii art studio

我记得在我的vfs的那个帖子里贴过这个工具的下载链接.

论坛徽章:
0
发表于 2008-08-26 19:27 |显示全部楼层
是的是的,你一说我就想起来了,下午晕晕的~~
3x

论坛徽章:
0
发表于 2008-08-27 11:55 |显示全部楼层
多谢LZ,好帖,认真学习  

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
发表于 2008-08-27 14:47 |显示全部楼层
好文章。另外,这张图是怎么放到正文的,我一般都是作为附件上传的

论坛徽章:
0
发表于 2009-04-05 16:19 |显示全部楼层
学习了 ,呵呵 谢谢LZ
前几天刚刚写了一个字符设备的驱动程序
正好解这个机会好好整理一下~~
诶,总是感觉太乱了,没有头绪
不知道LZ和大家是怎么看的

论坛徽章:
0
发表于 2009-04-05 16:35 |显示全部楼层
原帖由 nciae 于 2009-4-5 16:19 发表
学习了 ,呵呵 谢谢LZ
前几天刚刚写了一个字符设备的驱动程序
正好解这个机会好好整理一下~~
诶,总是感觉太乱了,没有头绪
不知道LZ和大家是怎么看的


多看几遍,思路就慢慢清晰了。

论坛徽章:
2
申猴
日期:2013-12-26 22:11:31天秤座
日期:2014-12-23 10:23:19
发表于 2009-04-07 10:25 |显示全部楼层
应该是插入吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP