Linux内核修炼之kobject,ktype,kset,subsys关系

随着内核版本的发展,会有一些变化,无论怎样,变化的是形式,不变的是思想! 

那么他们之间具有什么关系?那应该不是‘小3‘也不是'小5‘的关系,总之这种关系超越了人们,构成了Linux,是一种"你中有我,我中有你“的关系,其实关系复杂了,语言是难以描述的,不过还是先从文字开始吧。本文基于内核版本linux2.6.30.4,从分析bus总线来初步了解kobj, ktype,kset,subsys关系.因为bus总线本身是一个容器,包含了它们!

kobject,ktpye,kset可以说是Linux内核最基本,也是最重要的数据结构了。如果把Linux比做一栋大夏,那么它们就是大夏的基石。

1. kobject
kobject第一次出现是在内核版本2.5.45,是Linux 2.6后引入的新的设备管理机制,在内核中由struct kobject表示。通过这个数据结构使所有设备在底层都具有统一的接口,kobject提供基本的对象管理,是构成Linux2.6设备模型的核心结构,它与sysfs文件系统紧密关联,每个在内核中注册的kobject对象都对应于sysfs文件系统中的一个目录。Kobject是组成设备模型的基本结构。类似于C++中的基类,它嵌入于更大的对象的对象中--所谓的容器--用来描述设备模型的组件。如bus,devices, drivers 都是典型的容器。这些容器就是通kobject连接起来了,形成了一个树状结构。这个树状结构就与/sys相对应。
A kobject is an object of type struct kobject. Kobjects have a name and a reference count. A kobject also has a parent pointer (allowing kobjects to be arranged into hierarchies), a specific type, and, perhaps, a representation in the sysfs virtual filesystem.
Kobjects are generally not interesting on their own; instead, they are usually embedded within some other structure which contains the stuff the code is really interested in.
struct kobject {
const char *name;
struct list_headentry;
struct kobject*parent; 
struct 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;
};
2. ktype
Kobj type数据结构包含三个域:一个release方法用于释放kobject占用的资源;一个sysfs ops指针指向sysfs操作表和一个sysfs文件系统缺省属性列表。Sysfs操作表包括两个函数store()和show()。当用户态读取属性时,show()函数被调用,该函数编码指定属性值存入buffer中返回给用户态;而store()函数用于存储用户态传入的属性值。
A ktype is a type associated with a kobject. The ktype controls what happens when a kobject is no longer referenced and the kobject's default representation in sysfs. 
struct kobj_type {
void (*release)(struct kobject *kobj);
struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};

其中struct sysfs_ops 定义如下:

struct sysfs_ops {
	ssize_t	(*show)(struct kobject *, struct attribute *,char *);
	ssize_t	(*store)(struct kobject *,struct attribute *,const char *, size_t);
};

例如bus的ktype是这样定义的:

static struct sysfs_ops bus_sysfs_ops = {
	.show	= bus_attr_show,
	.store	= bus_attr_store,
};
static struct kobj_type bus_ktype = {
	.sysfs_ops	= &bus_sysfs_ops,
};

3.kset

kset最重要的是建立上层(sub-system)和下层的(kobject)的关联性。kobject 也会利用它来分辨自已是属于那一個类型,然後在/sys 下建立正确的目录位置。而kset 的优先权比较高,kobject会利用自已的*kset 找到自已所属的kset,并把*ktype 指定成该kset下的ktype,除非沒有定义kset,才会用ktype來建立关系。Kobject通过kset组织成层次化的结构,kset是具有相同类型的kobject的集合,也可以说kset具有kobject所有的功能.
A kset is a group of kobjects all of which are embedded in structures of the same type. The kset is the basic container type for collections of kobjects. Ksets contain their own kobjects, for what it's worth. Among other things, that means that a kobject's parent is usually the kset that contains it, though things do not normally have to be that way.
When you see a sysfs directory full of entries, generally each of those entries corresponds to a kobject in the same kset.
struct kset {
struct list_head list; //the list of all kobjects for this kset
spinlock_t list_lock; //a lock for iterating over the kobjects
struct kobject kobj; //the embedded kobject for this kset (recursion, isn't it fun...)
struct kset_uevent_ops *uevent_ops;//the set of uevent operations for this kset.
};

总线初始化buses_init时,建立了bus_kset.

static struct kset *bus_kset;
int __init buses_init(void)
{
	bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
	if (!bus_kset)
		return -ENOMEM;
	return 0;
}

4.subsystem

如果说kset是管理kobject 的集合,那么subsystem 就是管理kset 的集合。它描述系统中某一类设备子系统,如block subsys表示所有的块设备,对应于sysfs文件系统中的block目录。类似的,devices subsys对应于sysfs中的devices目录,描述系统中所有的设备。一个具体总线可称之为subsystem.如I2C,SPI子系统等.它们是bus的子系统.
A subsystem is a collection of ksets which, collectively, make up a major sub-part of the kernel. Subsystems normally correspond to the top-level directories in sysfs. 值得说明的是在以前的版本中内核是有一个struct subsystem 来描述subsys,但后来被去掉了,不过subsystem这一思想依旧存在.注意到在linux2.6.30.4版本中bus_register()中的struct bus_type_private *priv的机构作为bus的susbsystem,但在linux3.0版本后就被struct subsys_private *priv; 取代。可见subsystem变化的只是形式,思想一直没变。
struct bus_type_private {
	struct kset subsys;
	struct kset *drivers_kset;
	struct kset *devices_kset;
	struct klist klist_devices;
	struct klist klist_drivers;
	struct blocking_notifier_head bus_notifier;
	unsigned int drivers_autoprobe:1;
	struct bus_type *bus;
};

在bus下注册一个总线的过程,就是形成一个子系统subsystem的过程:

int bus_register(struct bus_type *bus)
{
	int retval;
	struct bus_type_private *priv;
	
	priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);
        ...
	retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);
	if (retval)
		goto out;
	priv->subsys.kobj.kset = bus_kset;    //
	priv->subsys.kobj.ktype = &bus_ktype; //
	priv->drivers_autoprobe = 1;
             ...
}
 
 

 
 

下面这个图比较经典,直观的反映了kset 和kobj之间的关系

Linux内核修炼之kobject,ktype,kset,subsys关系_第1张图片

kset 本身嵌有一个kobj实体作为所以同类kobj的'父母亲',同时还维护一个链表kset child list, 这个链表中所有的kobj的kset分别指向“父母亲"的kset.


最后不得不说,要全部了解其中关系,涉及的东西太多了,要学习的东西也太多了,不过,不积跬步,无以至千里,继续努力!以后会继续结合内核源码分析....

 

 

相关参考:

hacktaojxnu的图解分析很值得一看:http://blog.csdn.net/hacktaojxnu/article/details/6717991 
http://lwn.net/Articles/51437/

 

你可能感兴趣的:(数据结构,linux,struct,list,linux内核,recursion)