kobject概念

kobject --- kernel对象的意思,是内核中类似面向对象的概念.
kobject可以被认为是最顶层的基类,其他类都是他的派生物。
C语言中不允许直接描述继承关系,所以使用了诸如在一个结构中嵌入另外一个结构的技术。
 
定义如下:
    struct kobject{
        const char        *name;
        struct list_head    entry;
        struct kobject        *parent;  //上一层kobject结构的指针
        struct kset        *kset;
        struct kobj_type    *ktype;
        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;
    };


1. kobject初始化:对kobject的初始化比较复杂。
 
a. 将整个kobject置0,这里通常使用memset()函数. 如果忘记对kobject的清零初始化,则在以后使用kobject时,可能会发生一些奇怪的错误。
 
b. 调用kobject_init()函数,用来设置kobject结构内部的一些成员,如设置kobject的引用计数为1。

    /**
     * kobject_init - initialize a kobject structure
     * @kobj: pointer to the kobject to initialize
     * @ktype: pointer to the ktype for this kobject.
     *
     * This function will properly initialize a kobject such that it can then
     * be passed to the kobject_add() call.
     *
     * After this function is called, the kobject MUST be cleaned up by a call
     * to kobject_put(), not by a call to kfree directly to ensure that all of
     * the memory is cleaned up properly.
     */
    void kobject_init(struct kobject*kobj, struct kobj_type *ktype)
    {
        char *err_str;
        if (!kobj){
            err_str = "invalid kobject pointer!";
            goto error;
        }
        if (!ktype){
            err_str = "must have a ktype to be initialized properly!\n";
            goto error;
        }
        if (kobj->state_initialized){
            /* do not error out as sometimes we can recover */
            printk(KERN_ERR "kobject (%p): tried to init an initialized "
             "object, something is seriously wrong.\n", kobj);
            dump_stack();
        }
        kobject_init_internal(kobj);
        kobj->ktype= ktype;
        return;
    error:
        printk(KERN_ERR "kobject (%p): %s\n", kobj, err_str);
        dump_stack();
    }
    EXPORT_SYMBOL(kobject_init);


c. 使用者必须至少设置kobject的名字,这是sysfs入口中使用的名字.可以用:
 
int kobject_set_name(struct kobject *kobj, const char *fmt, ...)
    /**
     * kobject_set_name - Set the name of a kobject
     * @kobj: struct kobject to set the name of
     * @fmt: format string used to build the name
     *
     * This sets the name of the kobject. If you have already added the
     * kobject to the system, you must call kobject_rename() in order to
     * change the name of the kobject.
     */
    int kobject_set_name(struct kobject*kobj, const char *fmt, ...)
    {
        va_list vargs;
        int retval;
        va_start(vargs, fmt);
        retval = kobject_set_name_vargs(kobj, fmt, vargs);
        va_end(vargs);
        return retval;
    }
    EXPORT_SYMBOL(kobject_set_name);


d. 为包含它的结构设置引用计数
。只要对象的引用计数存在,对象就必须存在。底层控制kobject引用计数的函数:
*kobject_get():引用计数+1
kobject_put(): 引用计数-1
 
    /**
     * kobject_get - increment refcount for object.
     * @kobj: object.
     */
    struct kobject *kobject_get(struct kobject*kobj)
    {
        if (kobj)
            kref_get(&kobj->kref);
        return kobj;
    }

    /**
     * kobject_put - decrement refcount for object.
     * @kobj: object.
     *
     * Decrement the refcount, and if 0, call kobject_cleanup().
     */
    void kobject_put(struct kobject*kobj)
    {
        if (kobj){
            if (!kobj->state_initialized)
                WARN(1, KERN_WARNING"kobject: '%s' (%p): is not "
                 "initialized, yet kobject_put() is being "
                 "called.\n", kobject_name(kobj), kobj);
            kref_put(&kobj->kref, kobject_release);
        }
    }

kobject的引用计数不足以防止竞态的产生。当kobject继续被使用时,不能卸载该模块。
 
e. 每个kobject必须有一个release方法,有趣的事,release函数并没有包含在kobject自身内。而是用kobj_type结构:
 
    struct kobj_type{
        void (*release)(struct kobject*kobj); //这个就是用来保存kobject release函数指针。
        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);
    };

每个kobject都需要一个相应的kobj_type结构,可以在两个不同的地方找到这个指针:
1) kobject结构中包含了一个成员(ktype)保存了该指针。
2) 如果kobject是kset的一个成员的话,kset会提供kobj_type指针。
    static inline struct kobj_type *get_ktype(struct kobject*kobj)
    {
        return kobj->ktype;  //用来查找指定kobject的kobj_type指针。
    }

2. kobject的层次结构:
 
内核用kobject结构将各个对象连接起来,组成一个分层的结构体系。
有2中独立的机制用于连接:parent指针和kset。
 
1. parent: kobject结构的parent成员 用来保存另一个kobject结构的指针,这个结构表示了分层结构中的上一层节点。parent指针最重要的用途是在sysfs分层结构中定位对象。
2. kset:是嵌入相同类型的kobject的集合。
kobj_type结构关心的是对象的类型,而kset结构关心的是对象的集合。这两个概念是分立的,同种类型的对象可以出现在不同的集合中。
实际上,kset是kobject的顶层容器类,在每个kset内部,都包含了自己的kobject,并且可以用多种处理kobject的方法处理kset.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值