设为首页 加入收藏

TOP

Linux设备管理(二)_从cdev_add说起
2016-12-28 08:16:15 】 浏览:7374
Tags:Linux 设备管理 cdev_add 说起

内核中关于字符设备的操作函数的实现放在"fs/char_dev.c"中,打开这个文件,首先注意到就是这个在内核中不常见的静态全局变量cdev_map(27),我们知道,为了提高软件的内聚性,Linux内核在设计的时候尽量避免使用全局变量作为函数间数据传递的方式,而建议多使用形参列表,而这个结构体变量在这个文件中到处被使用,所以它应该是描述了系统中所有字符设备的某种信息,带着这样的想法,我们可以在"drivers/base/map.c"中找到kobj_map结构的定义:


从中可以看出,kobj_map的核心就是一个struct probe指针类型、大小为255的数组,而在这个probe结构中,第一个成员next(21)显然是将这些probe结构通过链表的形式连接起来,dev_t类型的成员dev显然是设备号,get(25)和lock(26)分别是两个函数接口,最后的重点来了,void*作为C语言中的万金油类型,在这里就是我们cdev结构(通过后面的分析可以看出),所以,这个cdev_map是一个struct kobj_map类型的指针,其中包含着一个struct probe指针类型、大小为255的数组,数组的每个元素指向的一个probe结构封装了一个设备号和相应的设备对象(这里就是cdev),可见,这个cdev_map封装了系统中的所有的cdev结构和对应的设备号,最多为255个字符设备


了解了cdev_map的功能,我们就可以一探cdev_add()


函数很短,(460-461)就是将我们之前获得设备号和设备号长度填充到cdev结构中,kobject_get()(468)也没做什么事:


所以,核心工作显然是交给了kobj_map()


这个函数在内核的设备管理中占有重要的地位,这里我们只从字符设备的角度分析它的功能,先上实现


这个函数的设计也很单纯,就是封装好一个probe结构并将它的地址放入probes数组进而封装进cdev_map,(48-55)j就是根据传入的设备号的个数,将设备号和cdev依次封装到kmalloc_array分配的n个probe结构中,(57-63)就是遍历probs数组,直到找到一个值为NULL的元素,再将probe的地址存入probes。至此,我们就将我们的cdev放入的内核的数据结构,当然,cdev中大量属性都是由内核帮我们填充的。


将设备放入的内核,我们再来看看内核是怎么找到一个特定的cdev的,对一个字符设备的访问流程大概是:文件路径=>inode=>chrdev_open=>cdev->fops->my_chr_open。所以只要通过VFS找到了inode,就可以找到chrdev_open(),这里我们就来关注一个chrdev_open()是怎么从内核的数据结构中找到我们的cdev并回调里满的my_chr_open()的。首先,chrdev_open()尝试将inode->i_cdev(一个cdev结构指针)保存在局部变量p中(359),如果p为空,即inode->i_cdev为空(360),我们就根据inode->i_rdev(设备号)通过kobj_lookup搜索cdev_map,并返回与之对应kobj(364),由于kobject是cdev的父类,我们根据container_of很容易找到相应的cdev结构并将其保存在inode->i_cdev中(367),找到了cdev,我们就可以将inode->devices挂接到inode->i_cdev的管理链表中,这样下次就不用重新搜索,直接cdev_get()即可(378)。找到了我们的cdev结构,我们就可以将其中的操作方法集inode->i_cdev->ops传递给filp->f_ops(386-390),这样,我们就可以回调我们的设备打开函数my_chr_open()(392);



】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Scala调用url获取返回值 下一篇C++实现学生信息管理系统

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目