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); } }
发表评论