kobject,kset,子系统层次结构 、platform_device platform_driver
来源:互联网 发布:局部全局优化算法 编辑:程序博客网 时间:2024/06/08 00:10
为什么两个name的名字必须匹配才能实现device和driver的绑定?
(1)在内核初始化时kernel_init()->do_basic_setup()->driver_init()->platform_bus_init()初始化platform_bus(虚拟总线);
(2)设备注册的时候platform_device_register()->platform_device_add()->(pdev->dev.bus = &platform_bus_type)把设备挂在虚拟的platform bus下;
(3)驱动注册的时候platform_driver_register()->driver_register()->bus_add_driver()->driver_attach()->bus_for_each_dev(),对每个挂在虚拟的platform bus的设备作__driver_attach()->driver_probe_device(),判断drv->bus->match()是否存在并且是否执行成功,此时通过指针执行platform_match,比较strncmp(pdev->name, drv->name, BUS_ID_SIZE),如果相符就调用really_probe(实际就是执行的相应设备的platform_driver->probe(platform_device),注意platform_drv_probe的_dev参数是由bus_for_each_dev的next_device获得)开始真正的探测加载,如果probe成功则绑定该设备到该驱动。
个人对kobject的一点研究
kobject,kset,子系统层次结构
在LINUX中最让人不解的大概就是/sys下面的内容了
下面首先让我们来创建一个简单的platform设备,并从这个设备的视角进行深入,在此篇文章的深入过程中,我们只看kobeject的模型
我所使用的内核版本号为2.6.26,操作系统的内核版本号为2.6.27-7,暂未发现2.6.27-7与2.6.26的重大不同
首先写一个简单的模块
接下来是makefile
KDIR中的目录请改为各位实际运行中的内核目录
make之后进行模块的加载 sudo insmod ./test.ko
现在到sys目录中查看我们的设备是否已经加载上了
首先是/sys/bus/platform/devices/
在devices下,每一个连接文件都代表了一个设备
ls可看见test_ts,进入test_ts,ls可发现driver这个链接文件,ls-l查看,发现这个文件是连到/sys/bus/platform/drivers/test_ts的
这里需要说明的是连接的含义,并不是driver驱动存在于test_ts这个设备中,而是test_ts使用的驱动为/sys/bus/platform/drivers/test_ts
现在换到/sys/bus/platform/drivers这个目录下
ls查看会发现这里的文件都为目录,而非连接文件,说明这是驱动真正放置的位置
现在进入test_ts目录,然后ls,发现有一个test_ts的连接文件,ls –l查看可发现该文件连接到/sys/devices/platform/test_ts下
回到/sys/bus/platform/devices/下ls –l也会发现test_ts连接到/sys/devices/platform/test_ts
为什么test_ts这个设备放置于/sys/devices/platform下,而不是/sys/bus/platform/devices下呢
我认为和直观性有关,在sys下有这么几个目录block bus class dev devices firmware kernel module fs power
devices很直观的说明了设备在这个目录下,便于大家查找
而/sys/bus/platform/devices下的连接是为了分类查找
画了张目录图,如下,绿色框的为连接文件,绿色线条为连接的对象
题外话:我自身对于这样的分类不是很喜欢,臃肿 重复 而且信息也不好规划,希望在以后的版本能对sys进行大的改造
现在来看另两个图,也就是构成sys的核心kobject,首先第一个是我去掉了连接部分的内容 也就是绿色线条的目录图第二个是组成这个目录图的核心,kobject图,我也叫他层次图
不看大号绿色箭头右边的内容的话是不是发现两个架构相同?
对的,kobject的层次决定了目录的结构
kobeject图很大,但也不要担心,里面的内容其实不多,基础框架涉及3个主要结构kset kobject和ktype
在说明test_ts的注册之前,先让我们看一下sys下的两个基础目录bus,devices
首先是bus
bus的注册在/drivers/base/bus.c里
先看bus_uevent_ops,这是一个uevent的操作集(我也还没清楚uevent的用途,所以uevent的内容先放着)
然后到kset_create_and_add
首先需要创建一个kset容器
这里的ktype,也就是kset_ktype是一个操作集,用于为sys下文件的实时反馈做服务,例如我们cat name的时候就要通过ktype提供的show函数,具体什么怎么运用,将在后面讲解
现在回到kset_create_and_add中的kset_register,将建立好的kset添加进sys里
至此bus的目录就建立起来了
模型如下
接下来是devices,在/drivers/base/core.c里
过程和bus的注册一致,我就不复述了~
模型如下
然后是platform的注册
在platform的注册中,分为两个部分,一部分是注册到devices中,另一部分是注册到bus中,代码在/drivers/base/platform.c中
首先是device_register,注册的参数为platform_bus,如下所示
struct device platform_bus = {
.bus_id = "platform",
};
很简单,只有一个参数,表明了目录名
现在devices下的platform目录建立好了,模型如下,其中红线描绘了目录关系
现在到bus_register了
注册的参数platform_bus_type如下所示
在retval = kset_register(&priv->subsys)完成之后platform在bus下的模型如下图
有印象的话大家还记得在platform下面有两个目录devices和drivers吧~
现在就到这两个目录的注册了
priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);
注意这两条语句的头部
priv->devices_kset = kset_create_and_add
priv->drivers_kset = kset_create_and_add
可以清楚的看到bus_type_private下的devices_kset, drivers_kset分别连接到了devices,drivers的kset上
至此, devices的模型就建立好了,drivers模型的建立和devices是一致的,只是名字不同而已,我就不复述了,建立好的模型如下
好了~ 到了这里,bus,devices和platform的基础模型就就建立好了,就等设备来注册了
在platform模型设备的建立中,需要2个部分的注册,驱动的注册和设备的注册
platform_device_register(&test_device);
platform_driver_register(&test_driver);
首先看platform_device_register
注册参数为test_device,结构如下
static struct platform_device test_device = {
.name = "test_ts",
.id = -1,
//. resource
//.dev
};
这个结构主要描述了设备的名字,ID和资源和私有数据,其中资源和私有数据我们在这里不使用,将在别的文章中进行讲解
klist_add_tail(&dev->knode_bus, &bus->p->klist_devices)就是这一行
在这一行代码中将设备挂载到了bus下的devices链表下,这样,当驱动请求匹配的时候,platform总线就会历遍devices链表为驱动寻找合适的设备
现在来看一下test_device的模型
然后platform_driver_unregister,他的参数 test_driver的结构如下
从上面代码可以看出,在platform_driver中设置了probe, remove, shutdown, suspend或resume函数的话
则drv->driver也会设置成platform对应的函数
到这里test_driver的模型就建立好了,图就是最上面的层次图,我就不再贴了
到这里一个基本的框架就建立起来了~
下面,我开始对kobject kset和ktype做分析
先说说关系,ktype与kobject和kset这两者之前的关系较少,让我画一个图,是这样的
ktype依赖于kobject,kset也依赖于kobject,而kobject有时需要kset(所以用了一个白箭头),不一定需要ktype(真可怜,连白箭头都没有)
首先先说一下这个可有可无的ktype
到/sys/bus/platform下面可以看见一个drivers_autoprobe的文件
cat drivers_autoprobe可以查看这个文件的值
echo 0 > drivers_autoprobe则可以改变这个文件的值
drivers_autoprobe这个文件表示的是是否自动进行初始化
在
中可以看见这么一段代码
if (bus->p->drivers_autoprobe)
ret = device_attach(dev);
bus->p->drivers_autoprobe的值为真则进行匹配
而drivers_autoprobe这个文件则可以动态的修改这个值选择是否进行匹配
使用外部文件修改内核参数,ktype就是提供了这么一种方法
现在让我们看看ktype是怎么通过kobject进行运作的
首先是ktype及通过ktype进行运作的drivers_autoprobe的注册
ktype的挂载十分简单,因为他是和kobject是一体的
只有这么下面一句
priv->subsys.kobj.ktype = &bus_ktype;
这样就将bus_ktype挂载到了platform_bus_type的kobject上
drivers_autoprobe的注册如下
最后bus_attr_drivers_autoprobe的模型如下
进入到bus_create_file中
现在一切准备就绪,来看看怎么读取吧
首先是open,大概流程可以看我的另一篇文章<从文件到设备>,一直看到ext3_lookup
这里和ext3_lookup不同的是,sys的文件系统是sysfs文件系统,所以应该使用的lookup函数为sysfs_lookup(/fs/sysfs/dir.c)
有关在哪调用open还是请查阅我的另一篇文章<从文件到设备>中 nameidata_to_filp之后的操作
好的~ 现在进入到了sysfs_open_file中
现在已经为read和write操作准备好了
马上进入到read操作中
整个流程如上图所示,如何进入到sysfs_read_file在上面open的操作中已经说明了
我们就从sysfs_read_file开始分析(该文件在/fs/sysfs/file.c中)
现在进入bus_attr_show中
没什么好介绍了就是打印 buf + bus->p->drivers_autoprobe 从结果来看~ buf是空的
到这里,终于把内核的信息给打印出来了,千辛万苦,层层调用,就是为了取得上层kobject结构,逆运算再取得kobject的上层结构
大家是否对kobject有所了解了呢?~
在对kobject进行介绍之前 还是先把write操作讲完吧 哈哈~
write操作和read操作重要的步骤基本是一致的,只不过在最后的调用中
不进行打印而对内核的参数进行了修改而已
好~ 现在让我们来看看kobject吧
kobject的结构如下
kobject描述的是较具体的对象,一个设备,一个驱动,一个总线,一类设备
在层次图上可以看出,每个存在于层次图中的设备,驱动,总线,类别都有自己的kobject
kobject与kobject之间的层次由kobject中的parent指针决定
而kset指针则表明了kobject的容器
像platform_bus 和test_device的kset都是devices_kset
呢parent和kset有什么不同呢
我认为是人工和默认的区别,看下面这张图 ,蓝框为kset,红框为kobject 容器提供了一种默认的层次~ 但也可以人工设置层次
对于kobject现在我只理解了这么多,欢迎大家指出有疑问的地方
最后是kset,kset比较简单,看下面的结构
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
struct kset_uevent_ops *uevent_ops;
};
对于kset的描述,文档里也有介绍
/**
* struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
*
* A kset defines a group of kobjects. They can be individually
* different "types" but overall these kobjects all want to be grouped
* together and operated on in the same manner. ksets are used to
* define the attribute callbacks and other common events that happen to
* a kobject.
翻译过来大概就是
结构kset,一个指定类型的kobject的集合,属于某一个指定的子系统
kset定义了一组kobject,它们可以是不同类型组成但却希望捆在一起有一个统一的操作
kset通常被定义为回调属性和其他通用的事件发生在kobject上
可能翻译的不是很好,望大家见谅
从结构中能看出kset比kobject多了3个属性
list_head //列表
spinlock_t //共享锁
kset_uevent_ops //uevent操作集
list_head 连接了所有kobject中kset属性指向自己的kobject
而kset_uevent_ops则用于通知机制,由于uevent的作用我也没接触过,所以暂不解析uevent的机制了
写到这里,不知道大家对内核驱动架构中的注册和对kobject的了解有无加深呢?
现在来看另两个图,也就是构成sys的核心kobject,首先第一个是我去掉了连接部分的内容 也就是绿色线条的目录图
对的,kobject的层次决定了目录的结构
kobeject图很大,但也不要担心,里面的内容其实不多,基础框架涉及3个主要结构kset kobject和ktype
在说明test_ts的注册之前,先让我们看一下sys下的两个基础目录bus,devices
首先是bus
bus的注册在/drivers/base/bus.c里
先看bus_uevent_ops,这是一个uevent的操作集(我也还没清楚uevent的用途,所以uevent的内容先放着)
然后到kset_create_and_add
首先需要创建一个kset容器
这里的ktype,也就是kset_ktype是一个操作集,用于为sys下文件的实时反馈做服务,例如我们cat name的时候就要通过ktype提供的show函数,具体什么怎么运用,将在后面讲解
现在回到kset_create_and_add中的kset_register,将建立好的kset添加进sys里
至此bus的目录就建立起来了
模型如下
模型如下
在platform的注册中,分为两个部分,一部分是注册到devices中,另一部分是注册到bus中,代码在/drivers/base/platform.c中
首先是device_register,注册的参数为platform_bus,如下所示
struct device platform_bus = {
.bus_id = "platform",
};
很简单,只有一个参数,表明了目录名
现在devices下的platform目录建立好了,模型如下,其中红线描绘了目录关系
注册的参数platform_bus_type如下所示
在retval = kset_register(&priv->subsys)完成之后platform在bus下的模型如下图
现在就到这两个目录的注册了
priv->devices_kset = kset_create_and_add("devices", NULL,&priv->subsys.kobj);
priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);
注意这两条语句的头部
priv->devices_kset = kset_create_and_add
priv->drivers_kset = kset_create_and_add
可以清楚的看到bus_type_private下的devices_kset, drivers_kset分别连接到了devices,drivers的kset上
至此, devices的模型就建立好了,drivers模型的建立和devices是一致的,只是名字不同而已,我就不复述了,建立好的模型如下
在platform模型设备的建立中,需要2个部分的注册,驱动的注册和设备的注册
platform_device_register(&test_device);
platform_driver_register(&test_driver);
首先看platform_device_register
注册参数为test_device,结构如下
static struct platform_device test_device = {
.name = "test_ts",
.id = -1,
//. resource
//.dev
};
这个结构主要描述了设备的名字,ID和资源和私有数据,其中资源和私有数据我们在这里不使用,将在别的文章中进行讲解
klist_add_tail(&dev->knode_bus, &bus->p->klist_devices)就是这一行
在这一行代码中将设备挂载到了bus下的devices链表下,这样,当驱动请求匹配的时候,platform总线就会历遍devices链表为驱动寻找合适的设备
现在来看一下test_device的模型
从上面代码可以看出,在platform_driver中设置了probe, remove, shutdown, suspend或resume函数的话
则drv->driver也会设置成platform对应的函数
到这里test_driver的模型就建立好了,图就是最上面的层次图,我就不再贴了
到这里一个基本的框架就建立起来了~
先说说关系,ktype与kobject和kset这两者之前的关系较少,让我画一个图,是这样的
首先先说一下这个可有可无的ktype
到/sys/bus/platform下面可以看见一个drivers_autoprobe的文件
cat drivers_autoprobe可以查看这个文件的值
echo 0 > drivers_autoprobe则可以改变这个文件的值
drivers_autoprobe这个文件表示的是是否自动进行初始化
在
中可以看见这么一段代码
if (bus->p->drivers_autoprobe)
ret = device_attach(dev);
bus->p->drivers_autoprobe的值为真则进行匹配
而drivers_autoprobe这个文件则可以动态的修改这个值选择是否进行匹配
使用外部文件修改内核参数,ktype就是提供了这么一种方法
现在让我们看看ktype是怎么通过kobject进行运作的
首先是ktype及通过ktype进行运作的drivers_autoprobe的注册
ktype的挂载十分简单,因为他是和kobject是一体的
只有这么下面一句
priv->subsys.kobj.ktype = &bus_ktype;
这样就将bus_ktype挂载到了platform_bus_type的kobject上
drivers_autoprobe的注册如下
最后bus_attr_drivers_autoprobe的模型如下
进入到bus_create_file中
现在一切准备就绪,来看看怎么读取吧
首先是open,大概流程可以看我的另一篇文章<从文件到设备>,一直看到ext3_lookup
这里和ext3_lookup不同的是,sys的文件系统是sysfs文件系统,所以应该使用的lookup函数为sysfs_lookup(/fs/sysfs/dir.c)
有关在哪调用open还是请查阅我的另一篇文章<从文件到设备>中 nameidata_to_filp之后的操作
好的~ 现在进入到了sysfs_open_file中
现在已经为read和write操作准备好了
马上进入到read操作中
我们就从sysfs_read_file开始分析(该文件在/fs/sysfs/file.c中)
现在进入bus_attr_show中
没什么好介绍了就是打印 buf + bus->p->drivers_autoprobe 从结果来看~ buf是空的
到这里,终于把内核的信息给打印出来了,千辛万苦,层层调用,就是为了取得上层kobject结构,逆运算再取得kobject的上层结构
大家是否对kobject有所了解了呢?~
在对kobject进行介绍之前 还是先把write操作讲完吧 哈哈~
write操作和read操作重要的步骤基本是一致的,只不过在最后的调用中
不进行打印而对内核的参数进行了修改而已
好~ 现在让我们来看看kobject吧
kobject的结构如下
kobject描述的是较具体的对象,一个设备,一个驱动,一个总线,一类设备
在层次图上可以看出,每个存在于层次图中的设备,驱动,总线,类别都有自己的kobject
kobject与kobject之间的层次由kobject中的parent指针决定
而kset指针则表明了kobject的容器
像platform_bus 和test_device的kset都是devices_kset
呢parent和kset有什么不同呢
我认为是人工和默认的区别,看下面这张图 ,蓝框为kset,红框为kobject
对于kobject现在我只理解了这么多,欢迎大家指出有疑问的地方
最后是kset,kset比较简单,看下面的结构
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
struct kset_uevent_ops *uevent_ops;
};
对于kset的描述,文档里也有介绍
/**
* struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
*
* A kset defines a group of kobjects. They can be individually
* different "types" but overall these kobjects all want to be grouped
* together and operated on in the same manner. ksets are used to
* define the attribute callbacks and other common events that happen to
* a kobject.
翻译过来大概就是
结构kset,一个指定类型的kobject的集合,属于某一个指定的子系统
kset定义了一组kobject,它们可以是不同类型组成但却希望捆在一起有一个统一的操作
kset通常被定义为回调属性和其他通用的事件发生在kobject上
可能翻译的不是很好,望大家见谅
从结构中能看出kset比kobject多了3个属性
list_head //列表
spinlock_t //共享锁
kset_uevent_ops //uevent操作集
list_head 连接了所有kobject中kset属性指向自己的kobject
而kset_uevent_ops则用于通知机制,由于uevent的作用我也没接触过,所以暂不解析uevent的机制了
写到这里,不知道大家对内核驱动架构中的注册和对kobject的了解有无加深呢?
- kobject,kset,子系统层次结构 、platform_device platform_driver
- kobject,kset,子系统层次结构 、platform_device platform_driver
- kobject,kset,子系统层次结构 、platform_device platform_driver
- kobject,kset,子系统层次结构 、platform_device platform_driver
- kobject,kset,子系统层次结构 、platform_device platform_driver
- kobject,kset,子系统层次结构 、platform_device platform_driver
- kobject,kset,子系统层次结构
- kobject,kset,子系统层次结构
- kobject,kset,子系统层次结构
- 操作系统_再识(kobject,kset,子系统层次结构)
- 操作系统_再识(kobject,kset,子系统层次结构)
- platform_device&&platform_driver
- platform_driver, platform_device
- kobject&kset
- Kobject Kset
- >输入子系统层次结构
- platform_device和platform_driver
- platform_device和platform_driver
- platform_driver_register()--如何match之后调用probe
- 图的广度遍历
- 距离和相似度计算总结
- 动态规划与贪心算法
- mybatis 在开启二级缓存后 和悲观锁之间的
- kobject,kset,子系统层次结构 、platform_device platform_driver
- 杂记
- Tomcat 集群配置
- Java常用算法手册-01算法概述
- 第一次使用Android Studio时你应该知道的一切配置
- 中位数(rms2017模拟3-1)*【推理】
- Hackinglab_Ctf闯关攻略(基础题)(自己部分更改)
- container_of()宏
- 学习用requests, bs4 抓取网页特定的内容