linux驱动篇之 driver_register 过程分析(一)
来源:互联网 发布:烟台市网络党校下载 编辑:程序博客网 时间:2024/06/08 05:05
转载地址:http://blog.csdn.net/richard_liujh/article/details/45825333
个人笔记,欢迎转载,请注明出处,共同分享 共同进步
http://blog.csdn.net/richard_liujh/article/details/45825333
kernel版本3.10.14
driver_register顾名思义,是驱动程序的注册。但是很少是由我们写的驱动直接调用的,例如framebuffer中调用platform_driver_register,i2c中调用i2c_add_driver等等函数注册对应的驱动程序。虽然我们并没有直接调用driver_register,但是最终都是通过driver_register帮我们完成了驱动程序的注册。所以,了解driver_register的注册过程,对我们理解linux的设备驱动有很到的帮助。
我们借助常用的platform_driver_register开始分析driver_register的调用过程。
1.初始化总线类型(bus_type),注册probe等相关函数
在文件./drivers/base/platform.c中有platform_driver_register源代码:
上面注册了相应的probe remove shutdown 等函数后,开始调用driver_register这里我们需要注意,driver的总线类型(bus_type)被初始化为platform_bus_type
其中platform_bus_type也在文件./drivers/base/platform.c中有具体定义我们是已platform为例讲解,所以注册驱动的总线类型是platform的。如果是I2C总线呢?
其实也类似,例如在./drivers/i2c/i2c-core.c中有I2C注册函数i2c_register_driver源码(省略部分无关代码)
res = driver_register(&driver->driver);……return 0;}EXPORT_SYMBOL(i2c_register_driver);所以,如果注册的是i2c驱动,那么总线类型初始化为i2c_bus_type,也可以在文件./drivers/i2c/i2c-core.c中看到其定义当总线类型和probe、remove、shutdown等函数注册后,就开始调用driver_register注册对应的驱动了。
driver_register源代码在文件./drivers/base/driver.c中
为了更好阅读上面的代码,我将其化简如下2. driver_find分析
在driver_register中调用driver_find,driver_find名字很通俗易懂,可以简单理解为找“驱动”。由于从linux 2.6版本,内核采用设备驱动模型,所以所谓的“找驱动“还是了解一点设备驱动模型的知识比较好。
在文件./drivers/base/driver.c中有driver_find源码
我们注意通过注释和代码知道,driver_find 通过我们给定的name在某bus中寻找驱动。这个比较好理解,就像上学的时候,老师XX知道某个学生的名字(name),然后去他所在的班级(bus)找这个学生。如果找到过(一般没好事TT),就把学生叫出来好好教育一番....。那么driver_find找了所谓的驱动会怎样呢?我们观察driver_find的返回值,你会发现,这里返回的是指针,也就是说driver_find是一个指针函数喽。指针的类型是struct device_driver类型的。
struct device_driver 在文件 include/linux/device.h中定义
/*******************************************************************************************************************************
下面涉及到设备驱动,这里只是简单提一下,一时看不懂很正常。如果有时间还想把设备驱动专门写几篇博文
*******************************************************************************************************************************/
那么问题来了,driver_find到底是如何通过name在bus中寻找驱动呢。其实就是通过下面的代码实现的
所以实现了基本的面向对象管理机制,是构成Linux2.6设备模型的核心结构。它与sysfs文件系统紧密相连,在内核中注册的每个kobject对象对应sysfs文件系统中的一个目录。类似于C++中的基类,Kobject常被嵌入于其他类型(即:容器)中。如bus,devices,drivers都是典型的容器。这些容器通过kobject连接起来,形成了一个树状结构。Bus:在内核中注册的每条总线在该目录下对应一个子目录,如: i2c platform spi ide pci scsi等等 其中每个总线目录内又包含两个子目录:devices和drivers ,devices目录包含了在整个系统中发现的属于该总线类型的设备,drivers目录包含了注册到该总线。其实说这么多,就是想让读者了解一点,我们的driver和bus类型、Kobject,kset等有莫大的关联。至于具体的原理,大家可以自己找一些设备驱动的资料看看。这里就不详细说明了。
在文件./lib/kobject.c 文件中有kset_find_obj函数的源码
这里面涉及到了一个很常用很的宏函数list_for_each_entry,不知道的童鞋可以点击这里。kset_find_obj通过循环操作,,根据我们给的名字name在指定的bus中循环对比,查看是否有相同的名字name(这个name存放在kobj中)。其实这就是一个循环链表的遍历过程,kset和kobj里面都有链表指针next和prev。kset是a set of kobjects,kobj是kernel object,所以kset是一系列的kobj的组合。其中kset,内核中的解释是struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.那么这里有个重要的belonging to啦,也就是现在分词做定语。哈哈,belonging to a specific subsystem说的是kset(一系列kobjs)属于特定的子系统。所以,初学者我们可以这么思考,一个kobj应该是属于某个kset(或者说kobj在kset循环链表中),kset又是属于某个subsystem的。所以,我们要通过name去寻找驱动,就必须要知道bustype,然后得到kset,最后得到kobj才能去对比name是否相同。这时我们回头看看调用driver_find(drv->name, drv->bus);时,不就给了drv->bus,然后通过bus->p->drivers_kset得到了kset。总结driver_find过程如下:
1. driver_find,拿到了drv->name和drv->bus开始找驱动
2. kset_find_obj 通过driver_find传递的bus->p->drivers_kset,利用list_for_each_entry遍历kset循环链表。(kset结构体中有循环链表指针next和prev)
3. 遍历循环链表中每一个kobj中的成员变量name
4. 通过strcmp(kobject_name(k), name)比较drv->name 和kobj中的name,如果有相同则表示查找成功
5. return :如果找到,则返回device_driver的指针,如果没有找到则返回了NULL。
为了能更好的说明driver_find,我用下面的图示意一下。
通过下面driver_register的代码可以看出调用driver_find的作用,
通过判断driver_find的返回值other,如果if(other)条件成立,说明other不是NULL,也就是说driver_find查找成功。但driver_register是注册驱动程序,如果驱动已经注册过,就不需要再次注册了。如果已经注册,那么直接return -EBUSY;后面的操作就不需要进行了。所以driver_register调用driver_find是为了检验驱动是否已经被注册,防止重复注册。
==============================================================================
今天是抗日战争 反法西斯胜利70周年。看了阅兵,实在太震撼了,还是希望祖国繁荣富强。哈哈哈哈哈
==============================================================================
- linux驱动篇之 driver_register 过程分析(一)
- linux驱动篇之 driver_register 过程分析(一)
- linux驱动篇之 driver_register 过程分析(一)
- linux驱动篇之 driver_register 过程分析(二)bus_add_driver
- linux驱动篇之 driver_register 过程分析(二)bus_add_driver
- linux驱动篇之 driver_register 过程分析(二)bus_add_driver
- linux驱动注册过程分析--driver_register(一)
- linux I2C 驱动之----i2c驱动的注册过程(i2c_register_driver->driver_register(&driver->driver)->driver_find)
- linux I2C 驱动之----i2c驱动的注册过程(i2c_register_driver->driver_register(&driver->driver)->driver_find)
- linux I2C 驱动之----i2c驱动的注册过程(i2c_register_driver->driver_register(&driver->driver)->driver_find)
- linux I2C 驱动之----i2c驱动的注册过程(i2c_register_driver->driver_register(&driver->driver)->driver_find)
- LINUX驱动分析之RTC(一)
- LINUX驱动分析之RTC(一)
- LINUX驱动分析之RTC(一)
- LINUX驱动分析之RTC(一)
- 【linux驱动分析】之dm9000驱动分析(一):dm9000原理及硬件分析
- linux IDE驱动分析之Ide_driver的注册(一)
- 我对linux理解之driver_register
- C++:标准模板库Sort
- [HAL库学习之路]4.外部中断
- 设定超参数的启发式想法
- highcharts柱状图的高度跟柱状图上方显示的数字、提示框没关系
- 贝塞尔曲线收录:一关于CAShapeLayer的一些实用案例和技巧
- linux驱动篇之 driver_register 过程分析(一)
- php创建数数据表的简单实现
- 数安时代亮相2017第四届广东省网络安全宣传周
- Java线程(一):线程安全与不安全
- 人工智能被巨头主导令人担忧,创业企业如何介入
- mysql主从同步故障解决
- mysql 使用set names 解决乱码问题的原理 本人亲测
- 自旋锁和互斥锁
- js实现在线查看和编辑office文件