linux kobject设备模型详解

kobject, kobj_type, kset简介

kobject是linux设备模型中最基本的结构。要说明的是,linux内核虽然由C语言编写,但是内核在实现时,到处都体现出开发者面向对象的思想。所以,kobject也可以理解为所有驱动对象的基类。后面用到的驱动对象,几乎都是kobject的派生类。作为基类的kobject并不关心自己是如何实现的,所以,在内核中,没有用kobject直接定义的变量,kobject只是作为一个抽象的基类而存在。一般都是将kobject嵌入到另一个结构,这个结构就可以看做是kobject的一个子类。而kobject的子类会比较关心kobject的属性和方法。

kobject包含一个名字和一个引用计数器,这个引用计数器会记录由kobject派生的内核对象被引用的次数。所以,一个结构最多只能包含一个kobject对象,否则,该结构的引用计数会乱套的。

上面提到,关心kobject实现的并不是kobject自身而是包含kobject的结构,所以当不同的结构包含kobject后,kobject的属性会不同,kobject销毁时所做的操作会不同,kobject所表现出的类型也会不同。所以,kobject中包含了一个叫作kobj_type的结构。kobj_type的目标就是为不同类型的kobject提供不同的属性以及销毁方法。

有时候,某个设备的可能具有多个kobject的子类对象,或者某些设备具有相同的特性,为了便于管理,应该把这些对象统一放入一个容器中。这里要用到的容器就是kset。kset只是kobject的一个集合。对应到linux文件系统中,一个kset就是/sys下的一个文件夹。

 

kobject详细介绍

先看看kobject的结构:

struct kobject {

    const char    *name;            //可以给kobject起一个名字

    struct list_head  entry;

    struct kobject       *parent;   //kobject的父指针

    struct kset       *kset;            //kobject所属的kset

    struct kobj_type  *ktype;

    struct sysfs_dirent  *sd;              //kobject在sysfs中的层次结构,关于sysfs这里不做讨论

    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;

};

kobject的操作:

extern int kobject_set_name(struct kobject *kobj, const char *name, ...)

               __attribute__((format(printf, 2, 3)));

extern int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,

                va_list vargs);

上两个函数为设定kobject的名字。虽然从上面的结构定义中可以看到kobject的名字就是成员name所指向的字符串,但为kobject设定名字时,还是函数kobject_set_name,这样可以提高代码的可移植性。

 

static inline const char *kobject_name(const struct kobject *kobj)

{

    return kobj->name;

}

 

extern void kobject_init(struct kobject *kobj, struct kobj_type *ktype);

此函数初始化kobject中的entrykref,将state_in_sysfs设为0state_add_uevent_sent设为0state_remove_uevent_sent设为0state_initialized设为1,并根据传入的ktype设定kobj->ktype,而且ktype不能为空。

 

extern int __must_check kobject_add(struct kobject *kobj,

                  struct kobject *parent,

                  const char *fmt, ...);

此函数将一个已初始化好的kobject加入系统,第一个参数是需要加入的kobject,第二个参数是kobject的父结点,第三个参数是kobject的名字。若parent为空,且kobj->kset不为空,则将kobj->prent设为&kobj->kset->kobj。此函数的流程图如下:



 

extern int __must_check kobject_init_and_add(struct kobject *kobj,

                       struct kobj_type *ktype,

                       struct kobject *parent,

                       const char *fmt, ...);

从名字就可以看出来,这个函数是kobject_initkobject_add的组合

 

extern void kobject_del(struct kobject *kobj);

此函数只是将kobjectsysfskset中去掉,并不是删除kobject,删除kobject得靠kobject->ktype->release才行。kobject_del在把kobject从kset中去掉后,会把kset的引用值减1。

 

extern struct kobject * __must_check kobject_create(void);

动态分配一个kobject,将kobject的ktype设为&dynamic_kobj_ktype后,并初始化之。

 

extern struct kobject * __must_check kobject_create_and_add(const char *name,

                     struct kobject *parent);

从名字就可以看出来,这个函数是kobject_create和kobject_add的组合。

以上两个函数的流程图如下:



 

extern int __must_check kobject_rename(struct kobject *, const char *new_name);

此函数可以为一个已经添加到sysfs中的kobject重命名,同时也会改变kobjectsysfs中对应的文件名。此函数在重命名之前会先把kobject的引用值加1,在改完名后,会再把kobject的引用值减1。

 

extern int __must_check kobject_move(struct kobject *, struct kobject *);

此函数可以改变一个kobjectparent,并同时更新kobjectsysfs中的路径,更换完parent之后,函数会把kobject以前的parent的引用值减1

 

extern struct kobject *kobject_get(struct kobject *kobj);

此函数为kobject的引用值加1

 

extern void kobject_put(struct kobject *kobj);

此函数为kobject的引用值减1,若引用值减为0,则销毁此kobject

上面这两个函数的流程图如下:



 

extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);

获取kobjectsysfs中的路径。

 

 

ktype详细介绍

 

struct kobj_type {

    void (*release)(struct kobject *kobj);     //kobject销毁时所调用的函数,由kobject_put调用

    const struct sysfs_ops *sysfs_ops;         //对于attribute的操作

    struct attribute **default_attrs;

};

struct sysfs_ops {

    ssize_t    (*show)(struct kobject *, struct attribute *,char *);

    ssize_t    (*store)(struct kobject *,struct attribute *,const char *, size_t);

};

kobj_type中的后两个成员表示了kobjectsysfs中的各个属性,及各个属性的操作方法。

需要说明的是,每一个kobject都必须有一个release函数,而已每个kobject不能在release函数被调用之前被销毁。release的作用是清除为kobject分配的内存空间,不过在release被调用时,kobject->name是有效的,但是,release函数不能改变name,因为name的释放是在函数kobject_cleanup中做的。

 

kset详细介绍

 

struct kset {

    struct list_head list;       //此链表中保存了kset中所有的kobject

    spinlock_t list_lock;        //当遍历list时,使用的锁

    struct kobject kobj;         //居然递归嵌套,我晕。。。。

    const struct kset_uevent_ops *uevent_ops;  //暂时不讨论uevent

};

kset关联的操作:

extern void kset_init(struct kset *kset);

初始化kset中各个成员。

 

extern int __must_check kset_register(struct kset *kset);

此函数首先将kset加入sysfskset加入sysfs是通过kset中的成员kobject实现的,其实加入sysfs的不是kset本身,而是kset的成员kobject,可以通过kobjectcontainer_of找到kset)然后发出一个KOBJ_ADDuevent

 

extern struct kset * __must_check kset_create_and_add(const char *name,

                     const struct kset_uevent_ops *u,

                      struct kobject *parent_kobj);

此函数只是kset_createkset_register的组合,其中kset_create会动态生成一个kset,并将其初始化。如果想简单地生成一个kset并将其加入系统,可以调用此函数。

以上三个函数的流程图如下:



 

extern void kset_unregister(struct kset *kset);

此函数将kset从sysfs中移出,也就是将kset的成员kobject从sysfs中移出。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值