好记性不如铅笔头

kernel, linux, 操作系统

Linux内核subsystem的简单笔记

LDD3的第14章《Linux设备模型》一章节把Linux内核中的很多结构体串讲了一遍,满满的干货,非常值得一看,这里简单的笔记下代码注释吧。作者的语文实在太差,很多阅读心得不知道怎么笔记出来,还请各位高手勿喷~

subsystem基于kset,而kset又基于kobject,因此subsystem的很多基本属性可以从subsystem->kset->kobject中获取。

CONTENTS

\linux-2.6.11\include\linux\kobject.h

/* subsystem其实也是一个kobject,不过隐藏的较深,subsystem对应的kobject
地址为 subsystem->kset->kobject
*/
struct subsystem {
	struct kset		kset;
	struct rw_semaphore	rwsem; /* subsystem内部的锁 */
};

/* 定义个subsystem,注意这里定义好的名称为_name_subsys ,
注意这里的第二个参数会直接设置ktype
*/
#define decl_subsys(_name,_type,_hotplug_ops) \
struct subsystem _name##_subsys = { \
	.kset = { \
		.kobj = { .name = __stringify(_name) }, \
		.ktype = _type, \
		.hotplug_ops =_hotplug_ops, \
	} \
}
#define decl_subsys_name(_varname,_name,_type,_hotplug_ops) \
struct subsystem _varname##_subsys = { \
	.kset = { \
		.kobj = { .name = __stringify(_name) }, \
		.ktype = _type, \
		.hotplug_ops =_hotplug_ops, \
	} \
}

extern void subsystem_init(struct subsystem *);
extern int subsystem_register(struct subsystem *);
extern void subsystem_unregister(struct subsystem *);

/* 对一个subsystem增加引用计数  */
static inline struct subsystem * subsys_get(struct subsystem * s)
{
	return s ? container_of(kset_get(&s->kset),struct subsystem,kset) : NULL;
}

/* 减少引用计数 */
static inline void subsys_put(struct subsystem * s)
{
	kset_put(&s->kset);
}

/* subsystem的属性结构体,这里要和 sysfs_ops 区分开 */
struct subsys_attribute {
	struct attribute attr; /* 属性 */
	/* 注意show和store的第一个参数是subsystem */
	ssize_t (*show)(struct subsystem *, char *);
	ssize_t (*store)(struct subsystem *, const char *, size_t);  };

extern int subsys_create_file(struct subsystem * , struct subsys_attribute *);
extern void subsys_remove_file(struct subsystem * , struct subsys_attribute *);

 \linux-2.6.11\lib\kobject.c

/* 初始化一个subsystem,这里其实就是初始化里面的kset */
void subsystem_init(struct subsystem * s)
{
	init_rwsem(&s->rwsem);
	kset_init(&s->kset);
}

/**
 *	subsystem_register - register a subsystem.
 *	@s:	the subsystem we're registering.
 *
 *	Once we register the subsystem, we want to make sure that 
 *	the kset points back to this subsystem for correct usage of 
 *	the rwsem. 
 */

int subsystem_register(struct subsystem * s)
{
	int error;

	subsystem_init(s);
	pr_debug("subsystem %s: registering\n",s->kset.kobj.name);

	if (!(error = kset_add(&s->kset))) {
		if (!s->kset.subsys)
			s->kset.subsys = s;
	}
	return error;
}

void subsystem_unregister(struct subsystem * s)
{
	pr_debug("subsystem %s: unregistering\n",s->kset.kobj.name);
	kset_unregister(&s->kset);
}


/**
 *	subsystem_create_file - export sysfs attribute file.
 *	@s:	subsystem.
 *	@a:	subsystem attribute descriptor.
 */
/* 对subsystem增加一个属性

这里的函数实现方式和device,driver等都是类似的。
由于这些属性不是kobject的默认属性,因此不能在内部的kobject中直接注册
*/
int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
{
	int error = 0;
	if (subsys_get(s)) {
/* 看下调用函数,其实 subsys_attribute的内部的show和store函数在这里没有使用,
那么该如何调用到对应的函数呢,作者个人认为和file.c/check_perm函数的实现有关。
*/
		error = sysfs_create_file(&s->kset.kobj,&a->attr);
		subsys_put(s);
	}
	return error;
}


/**
 *	subsystem_remove_file - remove sysfs attribute file.
 *	@s:	subsystem.
 *	@a:	attribute desciptor.
 */

void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
{
	if (subsys_get(s)) {
		sysfs_remove_file(&s->kset.kobj,&a->attr);
		subsys_put(s);
	}
}

 

发表评论

8 − 4 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据