Linux设备模型(2)_Kobject


存档,转载于:http://www.wowotech.net/device_model/kobject.html


1. 前言

Kobject是Linux设备模型的基础,也是设备模型中最难理解的一部分(可参考Documentation/kobject.txt的表述)。因此有必要先把它分析清楚。

2. 基本概念

由“Linux设备模型(1)_基本概念”可知,Linux设备模型的核心是使用Bus、Class、Device、Driver四个核心数据结构,将大量的、不同功能的硬件设备(以及驱动该硬件设备的方法),以树状结构的形式,进行归纳、抽象,从而方便Kernel的统一管理。

而硬件设备的数量、种类是非常多的,这就决定了Kernel中将会有大量的有关设备模型的数据结构。这些数据结构一定有一些共同的功能,需要抽象出来统一实现,否则就会不可避免的产生冗余代码。这就是Kobject诞生的背景。

目前为止,Kobject主要提供如下功能:

  1. 通过parent指针,可以将所有Kobject以层次结构的形式组合起来。
  2. 使用一个引用计数(reference count),来记录Kobject被引用的次数,并在引用次数变为0时把它释放(这是Kobject诞生时的唯一功能)。
  3. 和sysfs虚拟文件系统配合,将每一个Kobject及其特性,以文件的形式,开放到用户空间(有关sysfs,会在其它文章中专门描述,本文不会涉及太多内容)。

注1:在Linux中,Kobject几乎不会单独存在。它的主要功能,就是内嵌在一个大型的数据结构中,为这个数据结构提供一些底层的功能实现。
注2:Linux driver开发者,很少会直接使用Kobject以及它提供的接口,而是使用构建在Kobject之上的设备模型接口。

3. 代码解析
3.1 在Linux Kernel source code中的位置

在Kernel源代码中,Kobject由如下两个文件实现:

  • include/linux/kobject.h
  • lib/kobject.c

其中kobject.h为Kobject的头文件,包含所有的数据结构定义和接口声明。kobject.c为核心功能的实现。

3.2 主要的数据结构

在描述数据结构之前,有必要说明一下Kobject, Kset和Ktype这三个概念。

Kobject是基本数据类型,每个Kobject都会在"/sys/“文件系统中以目录的形式出现。

Ktype代表Kobject(严格地讲,是包含了Kobject的数据结构)的属性操作集合(由于通用性,多个Kobject可能共用同一个属性操作集,因此把Ktype独立出来了)。
注3:在设备模型中,ktype的命名和解释,都非常抽象,理解起来非常困难,后面会详细说明。

Kset是一个特殊的Kobject(因此它也会在"/sys/“文件系统中以目录的形式出现),它用来集合相似的Kobject(这些Kobject可以是相同属性的,也可以不同属性的)。

  • 首先看一下Kobject的原型
* Kobject: include/linux/kobject.h line 60 */
truct kobject {
   const char *name;
   struct list_head    entry;
   struct kobject      *parent;
   struct kset     *kset;
   struct kobj_type    *ktype;
   struct sysfs_dirent *sd;
   struct kref     kref;
   unsigned int state_initialized:1;
   unsigned int state_in_sysfs:1;
   unsigned int state_add_uevent_sent:1;
   unsigned int state_remove_uevent_sent:1;
   unsigned int uevent_suppress:1;
};
 



name,该Kobject的名称,同时也是sysfs中的目录名称。由于Kobject添加到Kernel时,需要根据名字注册到sysfs中,之后就不能再直接修改该字段。如果需要修改Kobject的名字,需要调用kobject_rename接口,该接口会主动处理sysfs的相关事宜。

entry,用于将Kobject加入到Kset中的list_head。

parent,指向parent kobject,以此形成层次结构(在sysfs就表现为目录结构)。

kset,该kobject属于的Kset。可以为NULL。如果存在,且没有指定parent,则会把Kset作为parent(别忘了Kset是一个特殊的Kobject)。

ktype,该Kobject属于的kobj_type。每个Kobject必须有一个ktype,或者Kernel会提示错误。

sd,该Kobject在sysfs中的表示。

kref,"struct kref”类型(在include/linux/kref.h中定义)的变量,为一个可用于原子操作的引用计数。

state_initialized,指示该Kobject是否已经初始化,以在Kobject的Init,Put,Add等操作时进行异常校验。

state_in_sysfs,指示该Kobject是否已在sysfs中呈现,以便在自动注销时从sysfs中移除。 state_add_uevent_sent/state_remove_uevent_sent,记录是否已经向用户空间发送ADD uevent,如果有,且没有发送remove uevent,则在自动注销时,补发REMOVE uevent,以便让用户空间正确处理。

uevent_suppress,如果该字段为1,则表示忽略所有上报的uevent事件。

注4:Uevent提供了“用户空间通知”的功能实现,通过该功能,当内核中有Kobject的增加、删除、修改等动作时,会通知用户空间。有关该功能的具体内容,会在其它文章详细描述。


  • Kset的原型为

/* include/linux/kobject.h, line 159 */
struct kset {
    struct list_head list;
    spinlock_t list_lock;
    struct kobject kobj;
    const struct kset_uevent_ops *uevent_ops;
};


release,通过该回调函数,可以将包含该种类型kobject的数据结构的内存空间释放掉。

sysfs_ops,该种类型的Kobject的sysfs文件系统接口。

default_attrs,该种类型的Kobject的atrribute列表(所谓attribute,就是sysfs文件系统中的一个文件)。将会在Kobject添加到内核时,一并注册到sysfs中。

child_ns_type/namespace,和文件系统(sysfs)的命名空间有关,这里不再详细说明。


总结,Ktype以及整个Kobject机制的理解。
Kobject的核心功能是:保持一个引用计数,当该计数减为0时,自动释放(由本文所讲的kobject模块负责) Kobject所占用的meomry空间。这就决定了Kobject必须是动态分配的(只有这样才能动态释放)。

而Kobject大多数的使用场景,是内嵌在大型的数据结构中(如Kset、device_driver等),因此这些大型的数据结构,也必须是动态分配、动态释放的。那么释放的时机是什么呢?是内嵌的Kobject释放时。但是Kobject的释放是由Kobject模块自动完成的(在引用计数为0时),那么怎么一并释放包含自己的大型数据结构呢?

这时Ktype就派上用场了。我们知道,Ktype中的release回调函数负责释放Kobject(甚至是包含Kobject的数据结构)的内存空间,那么Ktype及其内部函数,是由谁实现呢?是由上层数据结构所在的模块!因为只有它,才清楚Kobject嵌在哪个数据结构中,并通过Kobject指针以及自身的数据结构类型,找到需要释放的上层数据结构的指针,然后释放它。


讲到这里,就清晰多了。所以,每一个内嵌Kobject的数据结构,例如kset、device、device_driver等等,都要实现一个Ktype,并定义其中的回调函数。同理,sysfs相关的操作也一样,必须经过ktype的中转,因为sysfs看到的是Kobject,而真正的文件操作的主体,是内嵌Kobject的上层数据结构!


顺便提一下,Kobject是面向对象的思想在Linux kernel中的极致体现,但C语言的优势却不在这里,所以Linux kernel需要用比较巧妙(也很啰嗦)的手段去实现,



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值