深入Linux内核架构—简介和概述(六)

一、对象管理和引用计数

内核中很多地方都需要跟踪记录C语言中结构的实例。尽管这些对象的用法大不相同,但各个不同子系统的某些操作非常类似,例如引用计数。这导致了代码复制。由于这是个糟糕的问题,因此在内核版本2.5的开发期间,内核采用了一般性的方法来管理内核对象。所引入的框架并不只是为了防止代码复制,同时也为内核不同部分管理的对象提供了一致的视图,在内核的许多部分可以有效地使用相关信息,如电源管理。

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

引用计数;

管理对象链表(集合);

集合加锁;

将对象属性导出到用户空间(通过 sysfs 文件系统)。

kobject实现面向对象管理机制,在内核中每注册一个kobject对象都对应于sysfs文件系统中的一个目录,而不是文件。

1、 一般性的内核对象

下列数据结构将嵌入其他数据结构中,用作内核对象的基础。

<linux/kobject.h>

kobject 不是通过指针与其他数据结构连接起来,而必须直接嵌入。这样做,通过管理 kobject达到对包含 kobject 对象的管理。由于 kobject 结构嵌入到内核的数据结构中,需要注意保持该结构较小。向该数据结构添加一个新成员,导致其他数据结构大小增加。嵌入的kobject 如下所示:

typedef struct sample_st {
...
    struct kobject kobj;
...
}sample_t;

kobject 结构各个成员描述如下所示。

k_name:对象的名称,可利用sysfs导出到用户空间。sysfs是一个虚拟文件系统,将系统的各种属性描述导出到用户空间。

sd:对应sysfs的文件目录,支持内核对象与sysfs之间的关联。

kref:kobject的引用计数,简化引用计数的管理。

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

kset:指向kset集合,将对象与其他对象放置到一个集合时,则需要kset。

parent:一个指向父对象的指针,用于在kobject之间建立目录层次结构。

ktype:指向kobject的属性描述符,包含kobject的数据结构的更多详细信息。最重要的是用于释放该数据结构资源的析构函数。

kobject抽象实际上提供在内核使用面向对象技术的可能性,而无需C++的所有额外机制(以及二进制代码大小的膨胀和额外开销)。

用于管理kobject的引用计数kref的结构如下所示:

<linux/kref.h>

处理kobject的标准方法

1、kobject_get:对kobject的引用计数器加1。

2、kobject_put:对kobject的引用计数器减1。

3、kobject_register/kobject_unregister:从目录层次结构中注册/删除对象,对象被添加到父对象中现存的集合中(如果有的话),同时在sysfs文件系统中创建一个对应项(目录)。

4、kobject_init:初始化一个kobject,即将引用计数器设置为初始值,初始化对象的链表元素。

5、kobject_cleanup:在不需要kobject(以及包含kobject的对象)时,释放分配的资源。

6、kobject_add:初始化一个内核对象,并使之显示在sysfs中。

在kref的设计中,将一个值封装在结构体中,防止直接操纵该值。

必须使用kref_init来初始化kref。

如果要使用某个对象,则需要首先调用kref_get对引用计数器加1。

在对象不再使用时,则需要调用kref_put将计数器减1。

2、对象集合kset

在很多情况下,必须将不同的内核对象归类到集合中,例如,所有字符设备集合,或所有基于PCI(Peripheral Component Interconnect,外围部件互联)的设备集合。数据结构定义如下:

<linux/kobject.h>

kset是内核对象的一个例子。由于管理集合的结构只能是内核对象,因此,可以通过struct kobject管理。kset中包含一个kobject实例kobj。它与集合中包含的各个kobject无关,只是用来管理kset对象本身。

另一个结构用于描述内核对象的共同特性。其定义如下:

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

3、引用计数

引用计数用于检测内核中有多少地方使用了某个对象。每当内核的一个部分需要某个对象所包含的信息时,则对该对象的引用计数加1。如果不再需要相应的信息,则对该对象的引用计数减1。在计数下降到0后,内核知道不再需要该对象,所以此时从内存中释放该对象。内核提供如下数据结构处理引用计数:

<linux/kref.h>

该数据结构只提供一个一般性的原子引用计数。“原子”在这里意味着,对该变量的加1和减1操作在多核处理器系统上也是安全的,多核处理器系统中可能会有多个代码路径同时访问一个对象。

辅助方法kref_init、kref_get和kref_put用于对引用计数器进行初始化、加1、减1操作。

尽管这样操作引用计数器不会有并发问题,但并不意味着并发访问包含kref的数据结构是安全的!,内核代码需要采取进一步措施,以保证多核处理器同时访问数据结构不会引起任何问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值