Kernel 设备模型基础框架kobject

    Linux设备模型的基础框架是基于 kobject, kset 和 kobj_type 三个基础数据结构实现的。这篇主要分析这三个基础数据结构的作用,以及相互之间的关系。

    1,kobject:

struct kobject {
    const char        *name;        // 该kobject的名字,用于 sysfs 文件系统下的文件夹名字
    struct list_head    entry;    // 同类型 kobject 链表节点
    struct kobject        *parent;    // 指向父节点 kset 的 kobject
    struct kset        *kset;        // 同类型kobject的集合
    struct kobj_type    *ktype;    // kobject的属性操作方法,以及 release 方法
    struct kernfs_node    *sd; /* sysfs directory entry */    // 该 kobject 在sysfs文件系统下的节点
    struct kref        kref;        // 引用计数
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
    struct delayed_work    release;
#endif
    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 是最基础的数据结构,从上述字段定义中,可以看出这个结构包含如下功能:

        (1)引用计数功能。一个kobject可能代表一个总线,设备或驱动等,这些实例在内核空间可能会被多个调度实体或对象指针引用,因此用一个引用计数结构 kref 来记录当前有多少对象引用该 kobject,当 kref 的引用计数减为0时,内核接口自动调用用户指定的release接口销毁该kobject对象。kref 数据结构的本质就是一个atomic类型的对象,内核提供了 kref_get() 和 kref_put() 两个接口用于对引用计数自增和自减:

    struct kref {
    refcount_t refcount;
};

typedef struct refcount_struct {
    atomic_t refs;    // 本质上就是一个 atomic 类型的字段
} refcount_t;

    接口:

static inline void kref_get(struct kref *kref)
{
    refcount_inc(&kref->refcount);    // kref 自增
}

static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
{
    if (refcount_dec_and_test(&kref->refcount)) {    // kref 自减
        release(kref);    // 如果减完之后为0,释放该 kref 对象
        return 1;
    }
    return 0;
}

    (2)链表组织结构功能。多个kobject对象链接在一个kset下,形成一个循环双向链表。字段entry是双向链表节点,kset指向该kobject所属的kset,parent一般指向kset中的kobject。

    (3)sysfs接口。一个kobject表示sysfs文件系统中的一个目录,方便用户在用户态访问内核态数据结构。字段sd表示该kobject在sysfs中的入口项,name表示kobject表示的目录名称,ktype表示该目录的操作接口,包含kobject对象的release接口,以及该目录下属性文件的读写接口。

    2,kset:

struct kset {
    struct list_head list;    // 用于连接该kset下所有kobject的链表节点
    spinlock_t list_lock;
    struct kobject kobj;    // 一个kset本质上也是一个 kobject
    const struct kset_uevent_ops *uevent_ops;    // 内核事件上报用户态接口,一般用于驱动的热插拔事件上报
} __randomize_layout;

    一个kset表示所有同类型的kobject的集合。kset内部通过包含一个kobject,用来同其下挂的所有kobject组成一个双向循环链表。同时其下挂的所有kobject的parent都指向kset中包含的这个kobject。uevent_ops是内核事件上报用户态机制,多用于设备和驱动的热插拔事件上报。

    3,kobj_type:

struct kobj_type {
    void (*release)(struct kobject *kobj);    // 同类型kobject对象的释放接口
    const struct sysfs_ops *sysfs_ops;    // kobject属性文件的读写接口
    struct attribute **default_attrs;    // kobject的属性
    const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
    const void *(*namespace)(struct kobject *kobj);
    void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};

    一个kobj_type主要用来定义kobject的属性文件的读写接口,以及kobject对象的释放操作。

    2,通过上述分析,我们可以画出 kobject,kset 和 kobj_type之间的关系:

    3,总结一下:kobject/kset通常用于其他对象结构的内置结构,如设备和驱动数据结构通常都包含一个kobject结构,实现引用计数,设备层次结构和sysfs操作等。

转载于:https://my.oschina.net/yepanl/blog/3051355

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值