深入linux内核架构1.3.14——Kernel设备模型基础框架kobject

首先什么是kobject:kobject是设备模型的核心

内核中很多地方都需要跟踪记录C语言中结构的实例(借鉴C++对象,内核里面有许多的结构体实例化),尽管这些对象的用法大不相同,但各个不同子系统的某些操作非常相似,例如引用计数,这导致了代码复制。

在内核版本2.5开发期间,内核采用了一般性的内核方法来管理内核对象,所引入的框架并不只是为了防止代码复制,同时也为内核不同部分管理的对象提供了一致的视图,在内核的许多部分可以有效地使用相关信息,如电源管理。

一般性内核对象机制可用于执行下列对象操作:

  • 引用计数
  • 管理对象链表(集合)
  • 集合加锁
  • 将对象属性导出到用户空间

2.6内核增加了一个引人注目的新特性------统一设备模型

设备模型提供了一个独立的机制专门来表示设备,并描述在系统中的拓扑结构

(1)代码重复最小化

(2)可以列出系统中所有的设备,观察到他们的状态,并且查看他们连接的总线

(3) 可以将设备和其对应的驱动联系起来

(4) 可以按照设备类型进行分类

Linux设备模型的基础框架是基于 kobject, kset 和 kobj_type 三个基础数据结构实现的

这篇主要分析这三个基础数据结构的作用,以及相互之间的关系。

 struct kobject {

const char *name; /*指向kobject的名字*/// 该kobject的名字,用于 sysfs 文件系统下的文件夹名字

struct list_head entry;// 同类型 kobject 链表节点

struct kobject *parent/*指向父kobject 实现层次结构*/ // 指向父节点 kset 的 kobject

struct kset *kset;// 同类型kobject的集合

struct kobj_type *ktype; // kobject的属性操作方法,以及 release 方法

struct sysfs_dirent *sd;/*指向sysfs_dirent结构体 这个结构体就表示kobject对象的层次结构*/ // 该 kobject 在sysfs文件系统下的节点

struct kref kref;/*提供引用计数 其核心成员是一原子型变量,用来表示内核对象的引用计数 内核通过该成员追踪内核对象生命周期*/

unsigned int state_initialized:1;

unsigned int state_in_sysfs:1;/*是否已经加入sysfs*/

unsigned int state_add_uevent_sent:1;

unsigned int state_remove_uevent_sent:1;

};

3、ktype

kobject对象被关联到一种特殊的类型 即ktype(kernel object type的缩写) ktype由kobj_type结构体来表示,定义于头文件

struct kobj_type {

void (*release)(struct kobject *kobj);

struct sysfs_ops *sysfs_ops;

struct attribute **default_attrs;

};

kobject不是通过指针与其它数据结构连接起来,而是必须直接嵌入,这样做通过管理kobject即达到了对包含kobject对象的管理。

由于kobject结构体会嵌入到内核的许多数据结构中,开发者需要注意保持该结构较小。向该数据结构添加一个新成员,则会导致其它数据结构大小的增加。(很明显)

kobject结构各个成员的语义:

1、k_name是对象的文本名称,可利用sysfs导出到用户空间,sysfs是一个虚拟文件系统,可以将系统的各种属性描述到处用户空间。sysfs是一个虚拟文件系统,可以将系统的各种属性导出到用户空间。sd即用于支持内核对象与sysfs之间的关联。

2、kref类型为struct kref,用于简化引用计数的管理。

3、entry是一个标准的链表元素,用于将若干kobject放置到一个链表中(这种情况下称为集合)

4、将对象与其它对象放置到一个集合时则需要kset

5、parent是一个指向父对象的指针,可用于在kobject直间建立层次结构。

 kobject功能一:引用计数功能(检测内核多少地方用了某个对象)

一个kobject可能代表一个总线,设备或驱动等,这些实例在内核空间可能会被多个调度实体或对象指针引用,因此用一个引用计数结构 kref 来记录当前有多少对象引用该 kobject,当 kref 的引用计数减为0时,内核接口自动调用用户指定的release接口销毁该kobject对象。kref 数据结构的本质就是一个atomic类型的对象,内核提供了 kref_get() 和 kref_put() 两个接口用于对引用计数自增和自减:

struct kref {
    refcount_t refcount;
};

typedef struct refcount_struct {
    atomic_t refs;    // 本质上就是一个 atomic 类型的字段
} refcount_t;

    接口:

static inline void kref_get(struct kref *kref)
{
    refcount_inc(&kref->refcount);    // kref 自增
}

static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
    if (refcount_dec_and_test(&kref->refcount)) {    // kref 自减
        release(kref);    // 如果减完之后为0,释放该 kref 对象
        return 1;
    }
    return 0;
}

kobject功能二:链表组织结构功能

个kobject对象链接在一个kset下,形成一个循环双向链表。字段entry是双向链表节点,kset指向该kobject所属的kset,parent一般指向kset中的kobject。

kobject功能三:sysfs接口

一个kobject表示sysfs文件系统中的一个目录,方便用户在用户态访问内核态数据结构。字段sd表示该kobject在sysfs中的入口项,name表示kobject表示的目录名称,ktype表示该目录的操作接口,包含kobject对象的release接口,以及该目录下属性文件的读写接口。

kset

kset嵌入了一个一个kobject的实例kobj。他与集合中包含的各个kobject无关,结构体kset如下:

struct kset {
    struct list_head list;    // 用于连接该kset下所有kobject的链表节点
    spinlock_t list_lock;
    struct kobject kobj;    // 一个kset本质上也是一个 kobject
    const struct kset_uevent_ops *uevent_ops;    // 内核事件上报用户态接口,一般用于驱动的热插拔事件上报
} __randomize_layout;

一个kset表示所有同类型的kobject的集合。kset内部通过包含一个kobject,用来同其下挂的所有kobject组成一个双向循环链表。同时其下挂的所有kobject的parent都指向kset中包含的这个kobject。uevent_ops是内核事件上报用户态机制,多用于设备和驱动的热插拔事件上报。

kobj_type:

kobj_type与内核对象的集合没什么关系,kset已经提供了集合功能。该结构提供了与sysfs文件系统的接口。如果多个对象通过该文件系统导出类似信息,则可以简化,使多个对象共享同一个ktype来提供所需的方法。

struct kobj_type {
    void (*release)(struct kobject *kobj);    // 同类型kobject对象的释放接口
    const struct sysfs_ops *sysfs_ops;    // kobject属性文件的读写接口
    struct attribute **default_attrs;    // kobject的属性
    const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
    const void *(*namespace)(struct kobject *kobj);
    void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};

kobject/kset通常用于其他对象结构的内置结构,如设备和驱动数据结构通常都包含一个kobject结构,实现引用计数,设备层次结构和sysfs操作等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值