分类: LINUX
2008-12-03 17:09:32
阅读了The Linux Device Model这一章节后,对kobject还是有些问题,于是找来kobject.c看看各个函数是如何实现的。
首先,了解下在代码中需要用到的一些结构体
struct kobject {
char * k_name;
char name[KOBJ_NAME_LEN];
struct kref kref;
struct list_head entry;
struct kobject * parent;
struct kset * kset;
struct kobj_type * ktype;
struct dentry * dentry;
};
一般来说内核不会仅仅创建一个孤立的kobject。Kobject更多的是用来控制更大的特定域的对象,因此,被嵌入到其他的结构体中,比如说cdev。
struct kobj_type {
void (*release)(struct kobject *);
struct sysfs_ops * sysfs_ops;
struct attribute ** default_attrs;
};
表示一个kobjct 被嵌入的结构类型. 使用 get_ktype 来获得关联到一个给定 kobject 的 kobj_type.
struct kset {
struct subsystem * subsys;
struct kobj_type * ktype;
struct list_head list;
struct kobject kobj;
struct kset_hotplug_ops * hotplug_ops;
};
一个 kset 的主要功能是容纳; 它可被当作顶层的给 kobjects 的容器类. 实际上, 每个 kset 在内部容纳它自己的 kobject,, 在许多情况下它可以以一个 kobject 相同的方式被对待. 值得注意的是 ksets 一直在 sysfs 中出现; 一旦一个 kset 已被建立并且加入到系统, 会有一个 sysfs 目录给它. kobjects 没有必要在 sysfs 中出现, 但是每个是 kset 成员的 kobject 都出现在那里.
static inline struct kobj_type * get_ktype(struct kobject * k)
假如kobj->kset和kobj-kset->ktype存在时,当前的ktype为kobj->kset->ktype,反之,t则是kobj->ktype
static int (struct *)
首先,调用获得一个get_ktype获得一个ktype,当ktype- default_attrs不为空时,循环的向kobj->dentry中增加属性,当返回错误时,跳出。
static int create_dir(struct kobject * kobj)
函数给kobject创建一个dir,成功的话填充该dir,否则销毁该dir
static int get_kobj_path_length(struct kobject *kobj)
采用循环的方式自底向上遍历,得到kobj的路径长度。
static void fill_kobj_path(struct kobject *kobj, char *path, int length)
自底向上的方式方式将kobj指定长度的路径填入path中
char *kobject_get_path(struct kobject *kobj, int gfp_mask)
首先调用get_kobj_path_length和kmalloc为path分配内存,分配失败时,返回空;否则,初始化path后向里面填充kobj的的整个路径
void kobject_init(struct kobject * kobj)
重置kobj->kref为1,初始化kobj->entry链表的头部,并设置kobj->kset
static void unlink(struct kobject * kobj)
如果kobj->kset存在时,采用信号量的方式删除当前已存在的链表,并重新初始化链表。Kobj计数器减1。
int kobject_add(struct kobject * kobj).
将kobj计数器加1,失败则返回-ENOENT。当kobj->k_name为空时,设置kobj->k_name =的值为kobj->name。将kobj->parent的引用计数器+1,并且赋值给parent。当kobj->kset存在时,设置kobj->kset->subsys->rwsem写信号量,探测parent的存在,否则,将&kobj->kset->kobj增加引用后赋值给他。在&kobj->kset->list中增加kobj->entry,并取消kobj->kset->subsys->rwsem写信号量。重新设置kobj->parent 指向parent,创建一个dir,判断是否成功,成功则调用kobject_hotplug处理kobj,失败则调用unlink处理kobj,并查看parent是否存在,parent计数器减1。
int kobject_register(struct kobject * kobj)
初始化kobj并且计数器加1。
int kobject_set_name(struct kobject * kobj, const char * fmt, ...)
首先对动态参数进行标准化处理,当need
int kobject_rename(struct kobject * kobj, char *new_name)
当前kobj计数器加1,失败则返回错误信息,再调用sysfs_rename_dir对其进行改名操作,计数器减1,返回结果。
void kobject_del(struct kobject * kobj)
对使用kobj用户程序发布移除提示,调用sysfs_remove_dir处理kobj,移除kobj连接。
void kobject_unregister(struct kobject * kobj)
依次次用kobject_del()和kobject_put()处理kobj,和kobject_register()对应
struct kobject * kobject_get(struct kobject * kobj)
调用kref_get()对引用计数器加1
void kobject_cleanup(struct kobject * kobj)
当kobj->k_name 和 kobj->name不等时,释放kobj->k_name ,将kobj->k_name设置为空。当kobj_type和kobj_type->release存在时,调用release释放kobj。当kobj->kset存在时,kobj->kset计数器减1。当kobj->parent存在时,kobj->parent计数器减1。
static void kobject_release(struct kref *kref)
调用kobject_cleanup()释放kref
void kobject_put(struct kobject * kobj)
调用kref_put使计数器减1
void kset_init(struct kset * k)
调用kobject_init初始化kset->kobj,并设置k->list链表头。
int kset_add(struct kset * k)
当k->kobj.parent 、k->kobj.kset 、k->subsys三者中,只有k->subsys存在时,将k->kobj.parent设置为k->subsys->kset.kobj。返回k->kobj加入hierarchy的结果。
int kset_register(struct kset * k)
初始化k,并且返回kset_add(k)的结果。
void kset_unregister(struct kset * k)
调用kobject_unregister注销掉k->kobj
struct kobject * kset_find_obj(struct kset * kset, const char * name)
锁上kset->subsys->rwsem的读信号量,遍历kset->list,找到kobject_name(k)和name相等的k,解锁信号量之后返回计数器加1的情况
void subsystem_init(struct subsystem * s)
初始化subsystem的读写信号量和kset
int subsystem_register(struct subsystem * s)
注册subsystem,当s->kset计数器成功加1后,并且s->kset.subsys不为空,则s->kset.subsys = s
void subsystem_unregister(struct subsystem * s)
调用kset_unregister()注销掉s->kset
int subsys_create_file(struct subsystem * s, struct subsys_attribute * a)
调用sysfs_create_file,增加subsystem 中的一个subsys_attribute
void subsys_remove_file(struct subsystem * s, struct subsys_attribute * a)
调用sysfs_remove_file,去除subsystem 指定的subsys_attribute