Chinaunix首页 | 论坛 | 博客
  • 博客访问: 291139
  • 博文数量: 49
  • 博客积分: 3083
  • 博客等级: 中校
  • 技术积分: 710
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 08:22
文章分类

全部博文(49)

文章存档

2009年(8)

2008年(41)

分类: 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;

};

一般来说内核不会仅仅创建一个孤立的kobjectKobject更多的是用来控制更大的特定域的对象,因此,被嵌入到其他的结构体中,比如说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->ksetkobj-kset->ktype存在时,当前的ktypekobj->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_lengthkmallocpath分配内存,分配失败时,返回空;否则,初始化path后向里面填充kobj的的整个路径

 

void kobject_init(struct kobject * kobj)

重置kobj->kref1,初始化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默认值20)时,将kobj->name赋值给name,否则分配更多的空间给name,分配失败或者need仍然不小于limit,释放内存,返回错误代码。当kobj->k_name存在,而且不等于 kobj->name时,释放kobj->k_name。最后设置kobj->k_name name

 

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_typekobj_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

 

 

 

阅读(2474) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~