LV06-04-linux设备模型-02-kobject相关的数据结构
kobject是什么?kset是啥?ktype是啥?有啥用?若笔记中有错误或者不合适的地方,欢迎批评指正😃。
点击查看使用工具及版本
PC端开发环境 | Windows | Windows11 |
Ubuntu | Ubuntu20.04.2的64位版本 | |
VMware® Workstation 17 Pro | 17.6.0 build-24238078 | |
终端软件 | MobaXterm(Professional Edition v23.0 Build 5042 (license)) | |
Win32DiskImager | Win32DiskImager v1.0 | |
Linux开发板环境 | Linux开发板 | 正点原子 i.MX6ULL Linux 阿尔法开发板 |
uboot | NXP官方提供的uboot,使用的uboot版本为U-Boot 2019.04 | |
linux内核 | linux-4.19.71(NXP官方提供) |
点击查看本文参考资料
分类 | 网址 | 说明 |
官方网站 | https://www.arm.com/ | ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档 |
https://www.nxp.com.cn/ | NXP官方网站 | |
https://www.nxpic.org.cn/ | NXP 官方社区 | |
https://u-boot.readthedocs.io/en/latest/ | u-boot官网 | |
https://www.kernel.org/ | linux内核官网 |
点击查看相关文件下载
分类 | 网址 | 说明 |
NXP | https://github.com/nxp-imx | NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库 |
nxp-imx/linux-imx/releases/tag/v4.19.71 | NXP linux内核仓库tags中的v4.19.71 | |
nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0 | NXP u-boot仓库tags中的rel_imx_4.19.35_1.1.0 | |
I.MX6ULL | i.MX 6ULL Applications Processors for Industrial Products | I.MX6ULL 芯片手册(datasheet,可以在线查看) |
i.MX 6ULL Applications ProcessorReference Manual | I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网) | |
Source Code | https://elixir.bootlin.com/linux/latest/source | linux kernel源码 |
kernel/git/stable/linux.git - Linux kernel stable tree | linux kernel源码(官网,tag 4.19.71) | |
https://elixir.bootlin.com/u-boot/latest/source | uboot源码 |
kobject是Linux设备模型的基本单元,也是设备模型中最难理解的一部分,可参考内核文档 kobject.txt - Documentation/kobject.txt,内核文档好像是参考这个的:The zen of kobjects LWN。
一、概述
1. kobject、kset和ktype
这里先引出三个概念:kobject、kset和ktype,在开始这一节的学习前,先大概了解一下:
- kobject是基本数据类型,每个kobject都会在”/sys/“文件系统中以目录的形式出现。
- kset是一个特殊的kobject(因此它也会在”/sys/“文件系统中以目录的形式出现),它用来集合相似的kobject(这些kobject可以是相同属性的,也可以不同属性的)。
- ktype代表kobject(严格地讲,是包含了kobject的数据结构)的属性操作集合。由于通用性,多个kobject可能共用同一个属性操作集,因此把ktype独立出来了。每个kobject都会指定一个ktype(包括kset内嵌的kobject)。
2. 有什么关系?
三者的关系大概如下:
- kset可批量管理kobject。
- kset继承自kobject,且将一组kobject串连成一个链表进行统一管理。
- kobject既可以通过parent指针找到上层kobject,也可以通过kset指针找到其上层kset。但上层kobject对象无法遍历到下层,所以较少使用。
二、kobject
1. 背景
前面知道inux设备模型的核心是使用bus、class、device、driver四个核心数据结构,将大量不同功能的硬件设备及其驱动,以树状结构的形式,进行归纳、抽象,从而方便kernel的统一管理。而硬件设备的数量、种类是非常多的,这就决定了kernel中将会有大量的有关设备模型的数据结构。这些数据结构一定有一些共同的功能,需要抽象出来统一实现,否则就会不可避免的产生冗余代码。这就是kobject诞生的背景。
2. kobject是什么?
kobject(内核对象)是内核中抽象出来的通用对象模型, 用于表示内核中的各种实体。 kobject是一个结构体, 其中包含了一些描述该对象的属性和方法。 它提供了一种统一的接口和机制,用于管理和操作内核对象。
kobject结构体定义在 kobject.h - include/linux/kobject.h -struct kobject:
1 | struct kobject { |
- name:该kobject的名称,通常用于在/sys 目录下创建对应的目录。由于kobject添加到kernel时,需要根据名字注册到sysfs中,之后就不能再直接修改该字段。如果需要修改kobject的名字,需要调用 kobject_rename() 接口,该接口会主动处理sysfs的相关事宜。
- entry:用于将kobject加入到kset中的list_head,也就是将 kobject 链接到父 kobject 的子对象列表中, 以建立层次关系。
- parent:指向parent kobject,以此形成层次结构(在sysfs就表现为目录结构)。
- kset:指向包含该 kobject 的 kset(可以为NULL), 用于进一步组织和管理 kobject。如果没有指定parent,则会把kset作为parent(kset是一个特殊的kobject)。
- ktype:该kobject属于的kobj_type,描述 kobject 的属性和操作。每个kobject必须有一个ktype,否则kernel会提示错误。
- sd:kernfs_node 类型,该kobject在sysfs中的层次结构。指向 sysfs 目录中对应的 kernfs_node, 用于访问和操作 sysfs 目录项。
- kref:struct kref 类型的变量,是一个可用于原子操作的引用计数。它用于对 kobject 进行引用计数, 确保在不再使用时能够正确释放资源。
- state_initialized:指示该kobject是否已经初始化,以在kobject的Init,Put,Add等操作时进行异常校验。
- state_in_sysfs:指示该kobject是否已在sysfs中呈现,以便在自动注销时从sysfs中移除。
- state_add_uevent_sent:记录是否已经向用户空间发送ADD uevent。
- state_remove_uevent_sent:记录是否已经向用户空间发送REMOVE uevent,
- uevent_suppress:如果该字段为1,则表示忽略所有上报的uevent事件。
uevent提供了“用户空间通知”的功能实现,通过该功能,当内核中有kobject的增删改等动作时,会通知用户空间。
3. kobject能做什么?
kobject主要提供如下功能:
(1)通过parent指针,可以将所有kobject以层次结构的形式组合起来。
(2)使用一个引用计数(reference count),来记录kobject被引用的次数,并在引用次数变为0时把它释放(这是kobject诞生时的唯一功能)。
(3)和sysfs虚拟文件系统配合,将每一个kobject及其特性,以文件的形式显示到用户空间(/sys 目录下的那些东西)。
Tips
(1)在Linux中,kobject几乎不会单独存在。它的主要功能,就是内嵌在一个大型的数据结构中,为这个数据结构提供一些底层的功能实现。
(2)Linux driver开发者,很少会直接使用kobject以及它提供的接口,而是使用构建在kobject之上的设备模型接口。
4. 在系统中的表现?
每一个 kobject 都会对应系统/sys/下的一个目录:
目录又是有多个层次, 所以对应 kobject 的树状关系如下图所示:
在 kobject 结构体中, parent 指针用于表示父 kobject, 从而建立了kobject 之间的层次关系, 类似于目录结构中的父目录和子目录的关系。 一个 kobject 可以有一个父 kobject 和多个子 kobject, 通过 parent 指针可以将它们连接起来形成一个层次化的结构,类似于目录结构中, 一个目录可以有一个父目录和多个子目录, 通过目录的路径可以表示目录之间的层次关系。 这种层次化的关系可以方便地进行遍历, 查找和管理, 使得内核对象能够按照层次关系进行组织和管理。 这种设计使得 kobject 的树状结构在内核中具有很高的灵活性和可扩展性。
5. kobject机制
kobject的核心功能是:保持一个引用计数,当该计数减为0时,自动释放kobject所占用的meomry空间。这就决定了kobject必须是动态分配的,因为只有这样才能动态释放。
kobject大多数的使用场景,是内嵌在大型的数据结构中(如kset、device_driver等),因此这些大型的数据结构,也必须是动态分配、动态释放的。
那么释放的时机是什么呢?是内嵌的kobject释放时。但是kobject的释放是由kobject模块自动完成的(在引用计数为0时),那么怎么一并释放包含自己的大型数据结构呢?
这时kobj_type就派上用场了。因为kobj_type中的release回调函数负责释放kobject(甚至是包含kobject的数据结构)的内存空间。
那么kobj_type及其内部函数,是由谁实现呢?是由上层数据结构所在的模块!因为只有它才清楚kobject嵌在哪个数据结构中,并通过kobject指针以及自身的数据结构类型,利用函数宏containerof找到需要释放的上层数据结构的指针,然后释放它。
所以,每一个内嵌kobject的数据结构,例如kset、device、device_driver等等,都要实现一个kobj_type,并定义其中的回调函数。同理,sysfs相关的操作也一样,必须经过kobj_type的中转,因为sysfs看到的是kobject,而真正的文件操作的主体,是内嵌kobject的上层数据结构!
kobject是面向对象的思想在Linux kernel中的极致体现,但C语言的优势却不在这里,所以Linux kernel需要用比较巧妙的手段去实现它。
这里出现的kobj_type、kset、引用计数等相关概念后面都会了解到的。
6. 相关API
6.1 kobject使用流程
- kobject大多数情况下(有一种例外,下面会提到)会嵌在其它数据结构中使用,其使用流程如下:
(1)定义一个struct kset类型的指针,并在初始化时为它分配空间,添加到内核中;
(2)根据实际情况,定义内嵌有kobject的自己所需的数据结构原型;
(3)定义一个适合自己的kobj_type,并实现其中回调函数release;
(4)在需要使用到包含kobject的数据结构时,动态分配该数据结构,并分配kobject空间,添加到内核中;
(5)每一次引用数据结构时,调用 kobject_get() 接口增加引用计数;引用结束时,调用 kobject_put() 接口,减少引用计数;
(6)当引用计数为0时,kobject模块会自动调用kobj_type所提供的release接口,释放上层数据结构以及kobject的内存空间。
- 有一种例外就是:开发者只需要在sysfs中创建一个目录,而不需要其它的kset、kobj_type的操作。这时可以直接调用 kobject_create_and_add() 接口,分配一个kobject结构并把它添加到内核中。
6.2 kobject的分配和释放
前面提到kobject必须动态分配,而不能静态定义或者位于堆栈之上,它的分配方法有两种。
6.2.1 通过kmalloc自行分配
第一种分配方法就是通过kmalloc自行分配(一般是跟随上层数据结构分配),并在初始化后添加到kernel。
6.2.1.1 kobject_init()
kobject_init()函数定义如下:
1 | /** |
kobject_init
:初始化通过kmalloc等内存分配函数获得的struct kobject指针。主要执行逻辑为:
(1)第17 - 24 行:确认kobj和ktype不为空;
(2)第25行:如果该指针已经初始化过(判断kobj→state_initialized),打印错误提示及堆栈信息(但不是致命错误,所以还可以继续);
(3)第32行:初始化kobj内部的参数,包括引用计数kref、list_head、各种标志等;
(4)第33行:将输入形参 ktype 赋予 kobj→ktype 。
6.2.1.2 kobject_add()
kobject_add() 定义如下:
1 | int kobject_add(struct kobject *kobj, struct kobject *parent, |
如果koibject需要添加到sysfs中,则必须要调用 kobject_add() 函数。它将初始化完成的kobject添加到kernel中,参数包括需要添加的kobject、该kobject的parent(用于形成层次结构,可以为空)、用于提供kobject name的格式化字符串。主要执行逻辑为:
(1)确认kobj不为空,确认kobj已经初始化,否则错误退出。
(2)调用内部接口 kobject_add_varg(),完成添加操作,具体调用逻辑如下:
在 populate_dir() 函数中逐个处理内核对象所属对象类型的默认属性,对每个属性,调用 sysfs_create_file() 函数在内核对象的目录下创建以属性名为名字的文件。kobject_add() 中只会为默认属性自动创建文件。
6.2.1.3 kobject_init_and_add()
kobject_init_and_add() 函数定义如下:
1 | int kobject_init_and_add(struct kobject *kobj, struct kobj_type *ktype, |
qis其实就是上面两个接口的一个组合。kobject_add_varg()解析格式化字符串,将结果赋予kobj→name,之后调用 kobject_add_internal() 接口,完成真正的添加操作。 kobject_add_internal() 将kobject添加到kernel,主要执行的逻辑为:
(1)校验kobj以及kobj→name的合法性,若不合法打印错误信息并退出;
(2)调用 kobject_get() 增加该kobject的parent的引用计数(如果存在parent的话);
(3)如果存在kset,则调用 kobj_kset_join()接口将本kobject加入到此kset的kobject链表中。同时,如果该kobject没有parent,却存在kset,则将它的parent设为kset(kset是一个特殊的kobject),并增加kset的引用计数;
(4)通过 create_dir() 接口,调用sysfs的相关接口,在sysfs下创建该kobject对应的目录;
(5)如果创建失败,则执行后续的回滚操作,否则将 kobj→state_in_sysfs置为1;
这种方式分配的kobject,会在引用计数变为0时,由kobject_put调用其 kobj_type 的release接口,释放内存空间,具体可参考后面有关kobject_put的笔记。
6.2.2 使用kobject_create()创建
kobject模块可以使用 kobject_create() 自行分配空间,并内置了一个ktype(dynamic_kobj_ktype),用于在计数为0时释放空间。
6.2.2.1 kobject_create()
kobject_create() 函数定义如下:
1 | struct kobject *kobject_create(void) |
该接口为kobj分配内存空间,并以dynamic_kobj_ktype
为参数,调用 kobject_init() 接口,完成后续的初始化操作。
6.2.2.2 kobject_add()
kobject_add() 函数在前面已经了解过了。
6.2.2.3 kobject_create_and_add()
kobject_create_and_add() 函数定义如下:
1 | struct kobject *kobject_create_and_add(const char *name, struct kobject *parent) |
其实就是 kobject_create() 和kobject_add() 的组合。
6.3 kobject引用计数的加减
引用计数是啥?后面会了解到的,这里主要是看一下object常用的api。
通过 kobject_get() 和 kobject_put() 可以修改kobject的引用计数kref,并在kref为0时,调用对应ktype的release接口,释放占用空间。
6.3.1 kobject_get()
kobject_get() 函数定义如下:
1 | /** |
6.3.2 kobject_put()
kobject_put() 函数定义如下:
1 | /** |
以内部接口 kobject_release() 为参数,调用 kref_put() 。kref模块会在引用计数为零时,调用 kobject_release() 。
6.3.3 kobject_release()
kobject_release() 函数定义如下:
1 | static void kobject_release(struct kref *kref) |
kobject_release() 函数通过kref结构,获取kobject指针,并调用 kobject_cleanup() 函数:
1 | /* |
kobject_cleanup() 负责释放kobject占用的空间,主要执行逻辑如下:
(1)检查该kobject是否有ktype,如果没有,打印警告信息;
(2)如果该kobject向用户空间发送了ADD uevent但没有发送REMOVE uevent,补发REMOVE uevent;
(3)如果该kobject有在sysfs文件系统注册,调用kobject_del接口,删除它在sysfs中的注册;
(4)调用该kobject的ktype的release接口,释放内存空间;
(5)释放该kobject的name所占用的内存空间;
7. 创建kobject demo
7.1 demo源码
可以直接看这里:05_device_model/02_kobject_create · 苏木/imx6ull-driver-demo - 码云 - 开源中国
点击查看详情
1 |
|
我们执行make编译,最后就会得到sdriver_demo.ko文件。
7.2 开发板验证
我们拷贝到开发板,然后加载驱动:
然后我们就可以在/sys目录下看到我们创建的 skobject1 和 skobject3,skobject2 位于 /sys/skobject1 目录下。卸载驱动模块的时候这几个目录都会被删除。
三、kset
1. kset是什么?
kset(内核对象集合)是一种用于组织和管理一组相关 kobject 的容器(或者说叫集合)。 kset 是 kobject 的一种扩展, 它提供了一种层次化的组织结构, 可以将一组相关的 kobject 组织在一起。
kset是一个特殊的kobject(它也会在”/sys/“文件系统中以目录的形式出现),它用来集合相似的kobject(这些kobject可以是相同属性的,也可以不同属性的)。
kset定义在kobject.h - include/linux/kobject.h - struct kset:
1 | ** |
- list:指向该kset下所有的kobject的链表。用于将 kset 链接到全局 kset 链表中, 以便对 kset 进行遍历和管理。
- list_lock:避免操作链表时产生竞态的自旋锁,确保线程安全性。
- kobj:该kset自己的kobject(kset是一个特殊的kobject,也会在sysfs中以目录的形式体现)。 用于在/sys 目录下创建对应的目录, 并与kset 关联。
- uevent_ops:struct kset_uevent_ops 类型,该kset的uevent操作函数集,当kset中的某些kobject对象状态发生变化需要通知用户空间时,调用其中对应的函数来完成。当任何kobject需要上报uevent时,都要调用它所从属的kset的uevent_ops,添加环境变量,或者过滤event(kset可以决定哪些event可以上报)。因此,如果一个kobject不属于任何kset时,是不允许发送uevent的。
kset 通过包含一个 kobject 作为其成员, 将 kset 本身表示为一个 kobject, 并使用 kobj 来管理和操作 kset。 通过 list 字段, kset 可以
链接到全局 kset 链表中, 以便进行全局的遍历和管理。 同时, list_lock 字段用于保护对 kset 链表的并发访问。 kset 还可以定义自己的 uevent 操作, 用于处理与 kset 相关的 uevent 事件, 例如在添加或删除 kobject 时发送相应的 uevent 通知。
这些字段共同构成了 kset 的基本属性和关系, 用于在内核中组织和管理一组相关的kobject。 kset 提供了一种层次化的组织结构, 并与 sysfs 目录相对应, 方便对 kobject 进行管理和操作。
2. kset和kobject的关系
在 Linux 内核中, kset 和 kobject 是相关联的两个概念, 它们之间存在一种层次化的关系,
(1)kset 是 kobject 的一种扩展: kset 可以被看作是 kobject 的一种特殊形式, 它扩展了 kobject并提供了一些额外的功能。 kset 可以包含多个 kobject, 形成一个层次化的组织结构。
(2)kobject 属于一个 kset: 每个 kobject 都属于一个 kset。kobject 结构体中的 struct kset *kset字段指向所属的 kset。 这个关联关系表示了 kobject 所在的集合或组织。 多个kset的时候如下图:
通过 kset 和 kobject 之间的关系, 可以实现对内核对象的层次化管理和操作。 kset 提供了对 kobject 的集合管理接口, 可以通过 kset 来迭代、 查找、 添加或删除 kobject。 同时, kset 也提供了特定于集合的功能, 例如在集合级别处理 uevent 事件。
总结起来, kset 和 kobject 之间的关系是: 一个 kset 可以包含多个 kobject, 而一个 kobject只能属于一个 kset。 kset 提供了对kobject 的集合管理和操作接口, 用于组织和管理具有相似特性或关系的 kobject。 这种关系使得内核能够以一种统一的方式管理和操作不同类型的内核对象。
3. 相关API
3.4 kset的初始化、注册
Kset是一个特殊的kobject,因此其初始化、注册等操作也会调用kobject的相关接口,除此之外,会有它特有的部分。另外,和kobject一样,kset的内存分配,可以由上层软件通过kmalloc自行分配,也可以由kobject模块负责分配。
3.4.1 kset_init()
kset_init() 函数定义如下:
1 | /** |
该接口用于初始化已分配的kset,主要包括调用 kobject_init_internal() 初始化其kobject,然后初始化kset的链表。需要注意的时,如果使用此接口,上层软件必须提供该kset中的kobject的ktype。
3.4.2 kset_register()
kset_register() 定义如下:
1 | /** |
先调用 kset_init(),然后调用 kobject_add_internal() 将其kobject添加到kernel。
3.4.3 kset_unregister()
kset_unregister() 定义如下:
1 | /** |
直接调用 kobject_put() 释放其kobject。当其kobject的引用计数为0时,即调用ktype的release接口释放kset占用的空间。
3.4.4 kset_create_and_add()
kset_create_and_add() 定义如下:
1 | struct kset *kset_create_and_add(const char *name, |
会调用内部接口 kset_create() 动态创建一个kset,并调用 kset_register() 将其注册到kernel。内部接口 kset_create() 使用kzalloc分配一个kset空间,并定义一个kset_ktype类型的ktype,用于释放所有由它分配的kset空间。
4. 创建kset demo
4.1 demo源码
可以直接看这里:05_device_model/03_kset_create · 苏木/imx6ull-driver-demo - 码云 - 开源中国
点击查看详情
1 |
|
然后执行make,编译出sdriver_demo.ko。
4.2 开发板验证
我们拷贝到开发板,然后加载驱动:
驱动加载之后,我们进入/sys/目录下,可以看到创建生成的 kset,如下图所示,我们进到 skset 目录下,可以看到创建的 2 个 kobject。
四、引用计数器
1. 什么是引用计数器?
引用计数器(reference counting) 是一种内存管理技术, 用于跟踪对象或资源的引用数量。它通过在对象被引用时增加计数值, 并在引用被释放时减少计数值, 以确定何时可以安全地释放对象或资源。
2. kref 简介
kref 是 Linux 内核中提供的一种引用计数器实现, 它是一种轻量级的引用计数技术, 用于管理内核中的对象的引用计数。在 Linux 系统中, 引用计数器用结构体 kref 来表示。struct kref 定义在kref.h - include/linux/kref.h - struct kref:
1 | struct kref { |
本质是一个 int 型变量。在使用引用计数器时, 通常会将结构体 kref 嵌入到其他结构体中, 例如struct kobject, 以实现引用计数的管理。
为了实现引用计数功能, struct kobject 通常会包含一个嵌入的 struct kref 对象。 这样可以通过对 struct kref 的操作来对 struct kobject 进行引用计数的管理, 并在引用计数减少到 0 时释放相关资源。
3. 相关API
3.1 kref_init()
kref_init() 定义如下:
1 | /** |
初始化一个 struct kref 对象。 在使用引用计数之前, 必须先调用此函数进行初始化。 初始化 kerf 的值为 1 。
3.2 kref_get()
kref_get() 定义如下:
1 | /** |
增加 struct kref 的引用计数。 每次调用此函数, 引用计数都会增加。 kref 计数值加 1 。
3.3 kref_put()
kref_put() 定义如下:
1 | static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)) |
减少 struct kref 的引用计数, 并在引用计数减少到零时调用 release 函数来进行资源的释放。 通常, release 函数会在其中执行对象的销毁和内存释放等操作。
3.4 refcount_set()
refcount_set() 定义如下:
1 | /** |
设置 kerf 的计数值。
4. kref demo
4.1 demo源码
可以看这里:05_device_model/04_kref · 苏木/imx6ull-driver-demo - 码云 - 开源中国
点击查看详情
1 |
|
4.2 开发板验证
我们把生成的驱动拷贝到开发板,然后加载,再卸载,可以看到计数值的变化情况:
驱动加载之后, 第一条打印为“skobject1 kref is 1”, 因为创建了 skobject1,所以引用计数器的值为 1, 如下图所示的(1)。 第二条打印为: “skobject1 kref is 2”, 因为在skobject1 目录下创建了子目录 skobject2,所以 skobject1 的计数器值为 2, skobject2 的计数器值为 1, 如下图所示的(2)。
可以扩展一下,加深理解:如上图(3)所示, 如果在 objectA 下面创建俩个 object, objectA 的 计数器值为 3。 如上图所示(4), 如果在 objectA 下面创建两个 object, 那么 objectA 的计数器值 为 3, 在 objectB 下创建 object,那么 objectB 的计数器值为 2, objectC 的计数器值为 1。
最后我们卸载驱动,当引用计数器的值为 0 时, 表示没有任何引用指向对象或资源, 可以安全地释放对象或资源, 并进行相关的清理操作。
五、ktype
1. kobj_type是什么
每个kobject对象都有一些属性,这些属性由kobj_type表示。kobj_type就是用于表征kobject的的一些属性,指定了删除kobject时要调用的函数,kobject结构体中有struct kref字段用于对kobject进行引用计数,当计数值为0时,就会调用kobj_type中的release函数对kobject进行释放,这个就有点类似于C++中的智能指针了;它还指定了通过sysfs显示或修改有关kobject的信息时要处理的操作,实际是调用show/store函数。
kobj_type定义在 struct kobj_type 中:
1 | struct kobj_type { |
- release:通过该回调函数,可以将包含该类型kobject的数据结构的内存空间释放掉。
- sysfs_ops:struct sysfs_ops 类型,该种类型的kobject的sysfs文件系统接口(读属性接口show及写属性接口store)。
- default_attrs:struct attribute 类型,该种类型的kobject的atrribute列表(所谓attribute,就是sysfs文件系统中的一个文件)。将会在kobject添加到内核时,一并注册到sysfs中。
- child_ns_type/namespace:和文件系统(sysfs)的命名空间有关,这里不再详细说明。
2. ktype与kobject的关系
- kobject 在创建的时候,默认设置 kobj_type 的值为 dynamic_kobj_ktype(在 kobject_create() 函数中设置的),通常 kobject 会嵌入在其他结构中来使用,因此它的初始化跟特定的结构相关,典型的比如 struct device 和 struct device_driver ;
- 在 /sys 文件系统中,通过 echo/cat 的操作,最终会调用到 show/store 函数,而这两个函数的具体实现可以放置到驱动程序中;
3. ktype demo
3.1 demo源码
可以看这里:05_device_model/05_ktype · 苏木/imx6ull-driver-demo - 码云 - 开源中国
点击查看详情
1 |
|
3.2 开发板验证
我们拷贝到开发板,然后加载驱动,卸载驱动,这个实验主要是通过ktype自定义了kobject对象释放的时候的回调函数:
可以看到,当释放的时候,会出现我们的自定义打印信息。
参考资料
【1】linux驱动开发—— 6、linux 设备驱动模型_什么是kobject-CSDN博客
【2】Linux设备模型剖析系列一(基本概念、kobject、kset、kobj_type)_device下的kobj-CSDN博客
【4】一张图掌握 Linux platform 平台设备驱动框架!【建议收藏】-CSDN博客
【5】关于kobjects、ksets和ktypes的一切你没想过需要了解的东西 — The Linux Kernel documentation