Linux设备模型<二>底层模型

A)Kobject

Kobject实现了基本的面向对象的管理机制,是构造Linux2.6设备驱动模型的核心结构,与Sysfs文件系统有着紧密的联系,在内核中所注册的每一个Kobject

对象在Sysfs文件系统中都有一个目录与之对应<include/linux/kobject.h>

Kobject的结构定义为:

struct kobject {

    const char        *name;               /*指向设备名称的指针*/

    struct list_head    entry;              /*kobject 之间的双向链表,与所属的kset形成环形链表*/

    struct kobject        *parent;          /*指向父对象的指针*/

    struct kset        *kset;                /*所属kset的指针*/

    struct kobj_type    *ktype;            /*负责对该kobject类型进行跟踪的struct kobj_type的指针*/

    struct sysfs_dirent    *sd;

    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;

};

其中的kref域表示该对象引用的计数,内核通过kref实现对象引用计数管理,一个 kobject 的其中一个关键函数是作为一个引用计数器, 给一个它被嵌入的对象. 只要对这个对象的引用存在, 这个对象( 和支持它的代码) 必须继续存在. 来操作一个 kobject 的引用计数的低级函数是:

struct kobject *kobject_get(struct kobject *kobj)

struct kobject *kobject_put(struct kobject *kobj)

一个对 kobject_get 的成功调用递增 kobject 的 引用计数并且返回一个指向 kobject 的指针. 如果, 但是, 这个 kobject 已经在被销毁的过程中, 这个操作失败, 并且 kobject_get 返回 NULL. 这个返回值必须总是被测试, 否则可能导致无法结束的令人不愉快的竞争情况.

Ktype 域是一个指向kobj type结构的指针,表示该对象的类型。

与Kobject相关联的函数有:

void kobject_init(struct kobject * kobj);kobject初始化函数。

int kobject_set_name(struct kobject *kobj, const char *format, ...); 设置指定kobject的名称。

struct kobject *kobject_get(struct kobject *kobj); 将kobj 对象的引用计数加1,同时返回该对象的指针。

void kobject_put(struct kobject * kobj); 将kobj对象的引用计数减1,如果引用计数降为0,则调用kobject release()释放该kobject对象。

int kobject_add(struct kobject * kobj);将kobj对象注册到Linux系统,挂接该kobject对象到kset的list链中,增加父目录各级kobject的引用计数,在其parent指向的目录下创建文件节点,并启动该类型内核对象的hotplug函数。

void kobject_del(struct kobject * kobj);从Linux设备层次(hierarchy)中删除kobj对象。。

int kobject_init_and_add(struct kobject *kobj,struct kobj_type *ktype, struct kobject *parent,const char format...);初始化kobject,并将kobject注册到Linux系统
B)Kobj_type的定义如下:

struct kobj_type {
    void (*release)(struct kobject *kobj);
    const struct sysfs_ops *sysfs_ops;
    struct attribute **default_attrs;
    const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
    const void *(*namespace)(struct kobject *kobj);
};

在kobj_type结构体当中release用于释放kobject资源当kobject引用计数为0的时候调用该函数,default_attrs成员保存了属性列表用于创建该类型的每一个

kobject,sysfs_ops提供了实现这些属性的方法。

struct attribute {
    char * name;
    ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
            char *buf);
    ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr,
             const char *buf, size_t count);
};

上述kobj_type的sysfs ops指针指向sysfs操作表和一个sysfs文件系统缺省属性列表。Sysfs操作表包括两个函数store()和show()。当用户态读取属性时,show()函数被调用,该函数编码指定属性值存入buffer中返回给用户态;而store()函数用于存储用户态传入的属性值。

attribute 属性,它以文件的形式输出到sysfs的目录当中。在kobject对应的目录下面。文件名就是name。文件读写的方法对应于kobj type中的sysfs ops。

C)keset是具有相同类型的kobject的集合在Sysfs中体现成一个目录其结构体定义如下:

struct kset {
    struct list_head list;链接该kset中所有kobject的链表头
    spinlock_t list_lock;自旋锁
    struct kobject kobj;嵌入的kobject
    const struct kset_uevent_ops *uevent_ops;处理热插播事件的操作集合
};

包含在kset中的所有kobject被组织成一个双向循环链表,list正是该链表的头

kset数据结构还内嵌了一个kobject对象(由kobj表示)所有属于这个kset 的kobject对象的parent域均指向这个内嵌的对象。

此外,kset还依赖于kobj的引用计数:

kset的引用计数实际上就是内嵌的kobject对象的引用计数。
如下图,kset与kobject的关系图

相关函数

void kset_init(struct kset *kset);kset的初始化。

struct kset *kset_get(struct kset *kset);和增加引用计数

struct kset *kset_put(struct kset *kset);减少引用计数。

int kset_register(struct kset *kset);在内核注册一个kset。

int kset_unregister(struct kset *kset)从内核中注销一个kset。

在Linux系统当中当系统配置发生变化时,如添加Kset到系统或者是移动kset一个通知会从内核空间发送到用户空间这就是热插拔事件,热插拔事件会导致用户空间中相应的处理程序(如udev,mdev)被调用,这些处理程序会通过加载驱动程序等来响应热插拔时间。

D)热插拔操作集合

struct kset_uevent_ops {
    int (* const filter)(struct kset *kset, struct kobject *kobj);
    const char *(* const name)(struct kset *kset, struct kobject *kobj);
    int (* const uevent)(struct kset *kset, struct kobject *kobj,
              struct kobj_uevent_env *env);
};

那么上面这三个函数什么时候会呗调用呢:当kset所管理的的kobject和kset发生变化时(加入、移动等)上面这三个函数将会被调用。

filter:英文意思好像有过滤的意思吧,它是决定是否将事件传递到用户空间,如果返回值为0,将不传递事件。

name:将字符串传递给用户空间的热插拔处理程序。

uenvnt:将用户空间需要的参数添加到环境变量。

struct kobj_uevent_env {
    char *envp[UEVENT_NUM_ENVP];
    int envp_idx;
    char buf[UEVENT_BUFFER_SIZE];
    int buflen;
};









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值