由kobject_create_and_add全面了解kobject

本文深入剖析Linux内核中kobject的概念及其实现原理,包括kobject相关的数据结构ktype、kset、kref,并详细介绍了kobject_create_and_add函数的工作流程。

一、引言

从v2.6开始linux引入了统一的设备模型,用kobject数据结构来描述设备。有了kobject,设备间的拓扑关系就一目了然了,它为设备管理带来了很大的便利。最近学习到kobject_create_and_add(),通过对这个函数的学习,可以全面细致地了解到kobject。p.s.本文相关代码基于linux 5.4.74。内容有点多,读不下去请跳转至文章末尾。

二、kobject相关数据结构

首先,简单了解下kobject相关的数据结构。
kobject结构体如下所示:

//代码路径kernel5.4/include/linux/kobject.h
struct kobject {
   
   
	const char		*name; //name指针指向kobject的名称
	struct list_head	entry;
	struct kobject		*parent; 
	struct kset		*kset;
	struct kobj_type	*ktype;
	struct kernfs_node	*sd; /* sysfs directory entry */
	struct kref		kref; //kobject refcount 引用计数,为1引用,为0释放
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
	struct delayed_work	release;
#endif
	//下面是一些标志变量,用位域的方式声明
	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;
};

在这些成员变量中,ktype、kset、kref值得注意。它们是对一个kobject的描述、分类和引用标识。

2.1 ktype

ktype指针指向了一个kobj_type的数据结构,该数据结构如下代码段所示:

struct kobj_type {
   
   
	void (*release)(struct kobject *kobj);//析构函数指针,指向析构函数,该函数在refcount为0时,清理所有”同类“的kobject并释放内存。
	const struct sysfs_ops *sysfs_ops;//指针指向”sysfs读写操作函数结构体“
	struct attribute **default_attrs;//指针指向attribute结构体数组,描述了属于该ktype的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);
};

kobj_type是对kobject的特性描述。ktype数据结构初始化将会在随后的kobject_init流程中看到。

2.2 kset

kset指针指向一个kset的数据结构,该数据结构如下代码段所示:

struct kset {
   
   
	struct list_head list;//kset链表
	spinlock_t list_lock;
	struct kobject kobj;//该kset的基类(就是说该kset中的kobject都长这样)
	const struct kset_uevent_ops *uevent_ops;//指针指向kset_uevent_ops结构体,用于处理kset中的kobject对象的热插拔操作。
} __randomize_layout;

kset是很多kobject的集合。一般来说,如果一个kobject属于某个kset,即kset->kobj是存在的,那么这个kset->kobj将作为该kobject的父对象。这一点在随后的kobject_add流程中体现。

2.3 kref

kref指针指向一个kref的数据结构,该数据结构如下代码段所示:

//路径/kernel5.4/linux/kref.h
struct kref {
   
   
	refcount_t refcount;
};

kref引用计数来标示kobject的生命周期,在对象初始化时,调用kref_init()来使kref->refcount被原子置1(这一步将会在随后的kobject_init流程中看到)。引用了该kobject的代码都要进行引用计数加一。只要这个refcount不为0,该kobject就会继续被保留在内存中,否则对象将被撤销、内存被释放。
refcount的初始化、增加和减少分别用下面函数来实现:

//路径/kernel5.4/linux/kref.h
static inline void kref_init(struct kref *kref)
{
   
   
	refcount_set(&kref->refcount, 1);
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值