kobject&kset

Kobject与Kset详解

简介:
关于kobject和kset的介绍


 

kobject

Table of Contents

1 Kobject

1.1 简介

Kobject 是Linux 2.6 引入的新的设备管理机制,在内核中由struct kobject数据结构 进行描述通过这个数据结构使所有设备在底层都具有统一的接口,kobject提供基本的对象管 理,是构成Linux2.6设备模型的核心结构,它与sysfs文件系统紧密关联,每个在内核中注 册的kobject对象都对应于sysfs文件系统中的一个目录。Kobject是组成设备模型的基本结 构。但是,它比较低调,从不单独使用,都是嵌套在别的数据结构中。类似于C++中的基 类,它嵌入于更大的对象的对象中–所谓的容器–用来描述设备模型的组件。如bus, devices, drivers 都是典型的容器。这些容器就是通过kobject连接起来了,形成了 一个树状结构。这个树状结构就与/sys相对应。

kobject 结构为一些大的数据结构和子系统提供了基本的对象管理,避免了类似机能的重 复实现。这些机能包括

  • 对象引用计数.
  • 维护对象集合.
  • 对象上锁.
  • 在用户空间的表示.

1.2 定义

Kobject结构定义为:

struct kobject {
const char *name; /* 指向设备名称的指针 */
struct list_head entry; /* 挂接到所在kset中去的单元 */
struct kobject *parent; /* 指向父对象(kobject)的指针 */
struct kset *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;
};

其中,重要的变量已经加了注释,这里再简要介绍一下:

  • kref:
    kref域表示该对象引用的计数,内核通过kref实现对象引用计数管理,内核提供两 个函数kobject_get()、kobject_put() 分别用于增加和减少引用计数,当引用计数为 0时,所有该对象使用的资源释放。
  • Ktype:
    域是一个指向kobj type结构的指针,表示该对象的类型。
  • parent
    指针指向kobject的父对象。因此,kobject就会在内核中构造一个对象层次结构, 并且可以将对各对象间的关系表现出来,就如你看到的,这便是sysfs的真正面目: 一个用户空间的文件系统,用来表示内核中kobject对象的层次结构。

1.3 相关函数

  • void kobject_init(struct kobject * kobj) kobject初始化函数。
  • int kobject_set_name(struct kobject *kobj, const char *format, …) 设置指定kobject的名称。
  • struct kobject *kobject_get(struct kobject *kobj) 将kobj 对象的引用计数加1,同时返回该对象的指针。
  • void kobject_put(struct kobject * kobj) 将kobj对象的引用计数减1,如果引用计数降为0,则调用kobject release()释放该 kobject对象。
  • int kobject_add(struct kobject * kobj) 将kobj对象加入Linux设备层次。挂接该kobject对象到kset的list链中,增加父目录 各级kobject的引用计数,在其 parent指向的目录下创建文件节点,并启动该类型内 核对象的hotplug函数。
  • int kobject_register(struct kobject * kobj) kobject注册函数。通过调用kobject init()初始化kobj,再调用kobject_add()完 成该内核对象的注册。
  • void kobject_del(struct kobject * kobj) 从Linux设备层次(hierarchy)中删除kobj对象。
  • void kobject_unregister(struct kobject * kobj) kobject注销函数。与kobject register()相反,它首先调用kobject del从设备层次 中删除该对象,再调用kobject put()减少该对象的引用计数,如果引用计数降为0, 则释放kobject对象。

2 Kobj type

kobject对象被关联到一种特殊的类型,即ktype。ktype由kobj_type结构体表示,定义于 <linux/kobject.h>中:

struct kobj_type {
void (*release)(struct kobject *kobj);
struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};
  • release指针 指向在kobject引用计数减至0时要被调用的析构函数。该函数负责释放 所有kobject使用的内存和其它相关清理工作。
  • ktype

是为了描述一族kobject所具有的普遍特性。因此,不再需要每个kobject都分别定 义自己的特性,而是将这些普遍的特性在ktype结构体中一次定义,然后所有“同类”的 kobject都能共享一样的特性。

  • sysfs_ops

指向sysfs操作表和一个sysfs文件系统缺省属性列表。Sysfs操作表包括两 个函数store()和show()。当用户态读取属性时,show()函数被调用,该函数编码指定属 性值存入buffer中返回给用户态;而store()函数用于存储用户态传入的属性值。

  • default_attrs

指向一个attribute结构体数组。这些结构体定义了该kobject相关的默认 属性。属性给定了对象的特征,如果该kobject被导出到sysfs中,那么这些属性都将相应 的作为文件而导出。其定义如下:

struct attribute {
const char *name;
struct module *owner;
mode_t mode;
};

它以文件的形式输出到sysfs的目录当中。在kobject对应的目录下面。文件 名就是name。文件读写的方法对应于kobj_type中的sysfs_ops。

3 kset

3.1 简介

kset 最重要的是建立上层(sub-system)和下层的(kobject)的关联性。kobject 也会利用 它了分辨自已是属于那一個类型,然後在/sys 下建立正确的目录位置。而kset 的优先权 比较高,kobject会利用自已的*kset 找到自已所属的kset,並把*ktype 指定成該kset下 的ktype,除非沒有定义kset,才会用ktype來建立关系。Kobject通过kset组织成层次化 的结构,kset是具有相同类型的kobject的集合,在内核中用kset数据结构表示。

3.2 定义

/**
* 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.
*
* @list: the list of all kobjects for this kset
* @list_lock: a lock for iterating over the kobjects
* @kobj: the embedded kobject for this kset (recursion, isn't it fun...)
* @uevent_ops: the set of uevent operations for this kset. These are
* called whenever a kobject has something happen to it so that the kset
* can add new environment variables, or filter out the uevents if so
* desired.
*/
struct kset { /**< 内核的某个子系统中的同一类型的内核对象的集合 */
struct list_head list; /**< 链表头 */
spinlock_t list_lock; /**< Spinlock */
struct kobject kobj; /**< 这个KSet中嵌入的 kobject */
struct kset_uevent_ops *uevent_ops; /**< 操作函数 */
};
  • list: 包含在kset中的所有kobject被组织成一个双向循环链表的表头。
  • list_lock: 遍历这个kset中的所有kobject所需持有的锁。
  • kobject: 数据结构中内嵌的kobject对象(由kobj域表示),所有属于这个kset 的kobject对象的parent域均指向这个内嵌的对象。此外,kset的引用计数实际上就是内嵌的 kobject对象的引用计数。

3.3 相关函数

  • kset_init(): 完成指定kset的初始化
  • kset_get()和kset_put(): 分别增加和减少kset对象的引用计数。
  • Kset_add()和kset_del(): 函数分别实现将指定keset对象加入设备层次和从其中删除
  • ksetregister() 和 ksetunregister(): 完成 kset的注册和注销。
<think>我们正在讨论Linux内核中的kobjectkset。用户希望绘制它们的类图并理解关系结构。回顾上一次回答:kobject是内核对象的基础,用于管理引用计数、生命周期、sysfs集成等;而kset(kernelobjectset)是kobject的集合,用于组织相关对象。现在需要详细解释kobjectkset的类图关系:1.kobject:是基础对象,每个kobject都嵌入到更大的结构体中(如device、driver)。2.kset:是一个容器,包含一组相关的kobjectkset本身也是一个kobject(它内嵌了一个kobject),因此它也具有kobject的所有特性(如引用计数、sysfs目录等),并且还能作为集合的容器。关系结构:-每个kobject可以属于一个kset(通过其kobj.kset字段指向所属kset)。-kset内部通过链表(list_head)来管理其包含的kobjectkset->list)。-ksetkobject(嵌入的)作为集合中所有kobject的父对象(在sysfs中体现为目录层次)。类图描述(采用UML风格):注意:由于是内核数据结构,我们用类图来表示它们的关系。首先,定义kobject结构:-属性:name,parent,kset,ktype,entry(链表节点),sd(sysfs目录)等。-方法:kobject_init(),kobject_add(),kobject_del(),kobject_put()等(这些是操作函数,不在结构体内,但在类图中可以表示为方法)。其次,定义kset结构:-属性:list(链表头,用于挂载kobject链表),kobj(内嵌的kobject),uevent_ops(事件操作)等。-方法:kset_create(),kset_register(),kset_unregister()等。关系:-kset内嵌了kobject,即kset具有一个kobject(组合关系)。-kset包含多个kobject,即ksetkobject是聚合关系(通过链表连接)。-kobject通过kset指针指向其所属的kset。此外,kobject还关联到kobj_type(描述对象类型,包含释放函数、sysfs操作等)。类图(用文本描述):classkobject{+name:constchar*+parent:structkobject*+kset:structkset*+ktype:structkobj_type*+entry:structlist_head+sd:structkernfs_node*...(还有其他字段)}classkset{+list:structlist_head//用于链接属于这个kset的所有kobject的链表头+kobj:structkobject//内嵌的kobject,代表这个集合本身+uevent_ops:conststructkset_uevent_ops*}classkobj_type{+release:void(*)(structkobject*)+sysfs_ops:structsysfs_ops*+default_attrs:structattribute**}关系说明:-kset"有一个"kobject(组合关系,强所有关系):即kset通过内嵌的kobject成为kobject。-kset"包含"kobject(聚合关系):每个kset有一个链表(list),所有属于该ksetkobject通过其entry字段链接到这个链表上。-kobject"属于"0个或1个kset(通过kobjectkset指针指向所属kset)。-kobject"有一个"kobj_type(指向kobj_type的指针),用于定义其行为(如释放函数、属性等)。另外,在sysfs中:-kset对应的kobject会在sysfs中创建一个目录(通过其内嵌的kobject)。-属于该ksetkobject的sysfs目录会作为该kset目录的子目录(因为ksetkobject是这些kobject的parent)。绘制类图(文本形式):```+----------------++----------------++-------------------+|kobject|<>---|kset||kobj_type|+----------------++----------------++-------------------+|name:char*||list:list_head||release:func||parent:kobj*||kobj:kobject||sysfs_ops:sysfs_ops*||kset:kset*||...||default_attrs:attr**||ktype:kobj_type*|+----------------++-------------------+|entry:list_head||...|+----------------+^|||+----------------+|kset|------------------------->[嵌入一个kobject,所以kset也是kobject]+----------------+||^|||||+--------------------------------+||||+-----------------+|||||+----------------+|||kobject|<---------+|+----------------+||...|||kset指针指向我|+--------->+----------------+通过list链接到kset的链表```但是,文本图形可能不够清晰,我们可以用文字描述:-kset结构体内嵌一个kobject(组合关系),因此kset本身就是一个kobject(继承关系,在C中通过结构体嵌入实现)。-kset有一个链表(list_head),用于链接属于该kset的所有kobject(每个kobject通过其entry字段加入到这个链表)。-kobject通过kset指针指向它所属于的kset(如果属于某个kset)。另外,kobject还有parent指针(指向父kobject,在sysfs中形成目录层次)。注意:parent不一定等于ksetkobject,但通常如果一个kobject属于一个kset,那么它的parent会被设置为ksetkobject(在kobject_add()中自动设置,除非显式指定了parent)。总结关系:kset->内嵌的kobject:1对1(组合)kset->kobject(多个):1对多(聚合)kobject->kset:1对1(关联)为了更精确,下面是内核中kobjectkset的定义(基于Linux内核源代码):kobject定义(简化):structkobject{constchar*name;structlist_headentry;//用于链接到kset的链表structkobject*parent;//父对象(sysfs中的父目录)structkset*kset;//所属的ksetstructkobj_type*ktype;//类型structkernfs_node*sd;//sysfs目录节点structkrefkref;//引用计数...};kset定义(简化):structkset{structlist_headlist;//用于挂载该kset中所有kobject的链表头spinlock_tlist_lock;structkobjectkobj;//内嵌的kobject,代表该kset本身conststructkset_uevent_ops*uevent_ops;};注意:kobject的entry字段用于链入ksetlist链表。使用类图表示:```+--------------------+|kobject|+--------------------+|-name:char*|+-------------------+|-parent:kobject*||kset||-kset:kset*|+-------------------+|-entry:list_head|<---->|-list:list_head|(一对多)|-*ktype||-kobj:kobject||...||-...|+--------------------++-------------------+^^|||嵌入(组合)|+-----------------------------+(kset内嵌kobject,因此kset也是一个kobject,但kset类型是kobject的扩展)```这里有一个重要的点:由于kset内嵌了kobject,当我们操作kset时,实际上是通过内嵌的kobject来管理kset在设备模型中的位置和属性。所以,最终的类图关系可以这样理解:-ksetkobject的子类(通过内嵌实现,因此kset拥有kobject的全部功能,并且增加了集合功能)。-kset包含多个kobject(通过链表管理)。在sysfs中的表现:-kset的内嵌kobject在sysfs中创建一个目录(例如/sys/bus/)。-每个属于该ksetkobject在sysfs中会显示为该kset目录下的子目录。现在,我们可以绘制一个更规范的类图(文本UML):```+------------------------++---------------------+|<<struct>>kobj_type||<<struct>>kobject|+------------------------++---------------------+|+release:func||+name:char*||+sysfs_ops:sysfs_ops*||+parent:kobject*||+default_attrs:attr**|<-------|+kset:kset*|+------------------------+1|+ktype:kobj_type*|关联|+entry:list_head||+sd:kernfs_node*|+---------------------+^|继承(嵌入)|+---------------------+|<<struct>>kset|+---------------------+|+list:list_head|(链表头)|+list_lock:spinlock||+kobj:kobject|(内嵌对象)|...|+---------------------+|1|聚合(通过list链接多个kobject)|+---------------------+|kobjects||(通过entry链入ksetlist)|+---------------------+```注意:在UML中,聚合关系用空心菱形表示。而组合关系用实心菱形。这里ksetkobject的聚合关系(kset包含多个kobject)以及kset内嵌kobject的组合关系(kset包含一个kobject)都要表示出来。由于文本限制,我们用箭头和文本描述。另外,每个kobject都有一个ktype,因此kobj_type被kobject关联(每个kobject都指向一个kobj_type)。用户还要求生成相关问题:1.kset和sysfs目录结构的关系是怎样的?2.kobject的ktype在内核中起什么作用?3.如何创建一个kset并添加kobject到其中?4.在设备模型中,kset如何用于组织设备?回答用户问题:我们将用以下方式呈现:-首先解释kobjectkset的关系(含文本类图)。-然后简要描述sysfs中的表现。-最后提供相关问题。</think> ### kobjectkset的类图关系解析 以下是kobjectkset在内核中的关系结构图示,采用UML类图风格表示(基于Linux 6.x内核数据结构): ``` $$ \begin{array}{c} \text{+-------------------+} \\ \text{| \textbf{kobject} |} \\ \text{+-------------------+} \\ \text{| - name: char* |} \\ \text{| - parent: kobject*|} \\ \text{| - kset: kset* |} \\ \text{| - ktype: kobj_type*|} \\ \text{| - entry: list_head|} \\ \text{| - sd: kernfs_node*|} \\ \text{+-------↑-----------↑} \\ \qquad \text{继承} \uparrow \quad \text{关联} \uparrow \\ \begin{array}{c} \text{+-------------------+} \quad \text{+-------------------+} \\ \text{| \textbf{kset} |} \quad \text{| \textbf{kobj_type} |} \\ \text{+-------------------+} \quad \text{+-------------------+} \\ \text{| - list: list_head |} \quad \text{| - release: func* |} \\ \text{| - kobj: kobject |} \quad \text{| - sysfs_ops: ops* |} \\ \text{| - uevent_ops: ops*|} \\ \text{+-------------------+} \\ \end{array} \\ \end{array} $$ ``` #### 核心关系说明: 1. **继承关系** kset **内嵌**一个kobject(组合关系) $$ \text{struct kset} \\{ \\ \quad \text{struct kobject kobj}; \\ \\}; $$ 这使得kset本身也是一个kobject,具有所有基本特性 2. **聚合关系** kset **包含**多个kobject(一对多关系) $$ \text{struct kset} \\{ \\ \quad \text{struct list_head list}; \\ \\}; $$ 每个kobject通过`entry`字段链接到该链表 3. **关联关系** - kobject通过`kset`指针指向所属的kset - kobject通过`ktype`指向其类型描述符 - kset通过`uevent_ops`处理热插拔事件 #### 关键数据结构源码解析 ```c // kobject核心结构 (include/linux/kobject.h) struct kobject { const char *name; // sysfs显示名称 struct list_head entry; // 链入kset的节点 struct kobject *parent; // sysfs父目录 struct kset *kset; // 所属集合 struct kobj_type *ktype; // 类型描述符 struct kernfs_node *sd; // sysfs目录节点 struct kref kref; // 引用计数 }; // kset结构 (include/linux/kobject.h) struct kset { struct list_head list; // 成员kobject链表头 spinlock_t list_lock; // 链表锁 struct kobject kobj; // 内嵌的kobject const struct kset_uevent_ops *uevent_ops; // 事件回调 }; // kobj_type结构 (include/linux/kobject.h) struct kobj_type { void (*release)(struct kobject *); // 对象销毁函数 const struct sysfs_ops *sysfs_ops; // sysfs操作集 const struct attribute_group **default_groups; // 默认属性组 }; ``` #### sysfs中的层次结构 当kobjectkset注册时,sysfs生成如下目录树: ``` /sys/ ├── bus/ ← kset (总线集合) │ ├── usb/ ← kset (USB子系统) │ │ ├── devices/ ← kset (设备容器) │ │ │ └── 1-1/ ← kobject (具体设备) │ │ └── drivers/ ← kset (驱动容器) └── class/ ← kset (设备类集合) └── net/ ← kset (网络设备) └── eth0/ ← kobject (网卡) ``` - 每个**kset**对应sysfs目录(由内嵌kobject创建) - 目录内容由`kobj_type`的`default_groups`定义 - 子目录通过`parent`指针建立层次 #### 生命周期运作流程 1. **创建对象** ```c struct my_obj { struct kobject kobj; int custom_data; }; ``` 2. **注册到kset** ```c kobject_init(&obj->kobj, &my_ktype); kobj_set_kset_s(&obj->kobj, my_kset); // 设置所属kset ret = kobject_add(&obj->kobj); ``` 3. **引用管理** ```c kobject_get(&obj->kobj); // 增加引用计数 kobject_put(&obj->kobj); // 减少引用计数 ``` 4. **销毁回调** 当计数归零时自动调用ktype的release函数 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值