个人对kobject的一点研究(2)

首先是bus
bus的注册在/drivers/base/bus.c里
int __init buses_init(void)
{
        bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
        if (!bus_kset)
                return -ENOMEM;
        return 0;
}

先看bus_uevent_ops,这是一个uevent的操作集(我也还没清楚uevent的用途,所以uevent的内容先放着)

然后到kset_create_and_add

struct kset *kset_create_and_add(const char *name,
                                 struct kset_uevent_ops *uevent_ops,
                                 struct kobject *parent_kobj)
//传递进来的参数为("bus", &bus_uevent_ops, NULL)
{
        struct kset *kset;
        int error;

        //创建一个kset容器
        kset = kset_create(name, uevent_ops, parent_kobj);
        if (!kset)
                return NULL;

        //注册创建的kset容器
        error = kset_register(kset);
        if (error) {
                kfree(kset);
                return NULL;
        }
        return kset;
}

首先需要创建一个kset容器
static struct kset *kset_create(const char *name,
                                struct kset_uevent_ops *uevent_ops,
                                struct kobject *parent_kobj)
//传递进来的参数为("bus", &bus_uevent_ops, NULL)
{
        struct kset *kset;

        //为kset分配内存
        kset = kzalloc(sizeof(*kset), GFP_KERNEL);
        if (!kset)
                return NULL;

        //设置kset中kobject的名字,这里为bus
        kobject_set_name(&kset->kobj, name);

        //设置uevent操作集,这里为bus_uevent_ops
        kset->uevent_ops = uevent_ops;

        //设置父对象,这里为NULL
        kset->kobj.parent = parent_kobj;

        //设置容器操作集
        kset->kobj.ktype = &kset_ktype;

        //设置父容器
        kset->kobj.kset = NULL;

        return kset;
}

这里的ktype,也就是kset_ktype是一个操作集,用于为sys下文件的实时反馈做服务,例如我们cat name的时候就要通过ktype提供的show函数,具体什么怎么运用,将在后面讲解

现在回到kset_create_and_add中的kset_register,将建立好的kset添加进sys里

int kset_register(struct kset *k)
{
        int err;

        if (!k)
                return -EINVAL;

        //初始化
        kset_init(k);

        //添加该容器
        err = kobject_add_internal(&k->kobj);
        if (err)
                return err;
        kobject_uevent(&k->kobj, KOBJ_ADD);
        return 0;
}

kset_init进行一些固定的初始化操作,里面没有我们需要关心的内容
kobject_add_internal为重要的一个函数,他对kset里kobj的从属关系进行解析,搭建正确的架构

static int kobject_add_internal(struct kobject *kobj)
{
        int error = 0;
        struct kobject *parent;

        //检测kobj是否为空
        if (!kobj)
                return -ENOENT;

        //检测kobj名字是否为空
        if (!kobj->name || !kobj->name[0]) {
                pr_debug("kobject: (%p): attempted to be registered with empty "
                         "name!\n", kobj);
                WARN_ON(1);
                return -EINVAL;
        }

        //提取父对象
        parent = kobject_get(kobj->parent);

        /* join kset if set, use it as parent if we do not already have one */
        //父容器存在则设置父对象
        if (kobj->kset) {//在bus的kset中为空,所以不会进入到下面的代码

                //检测是否已经设置父对象
                if (!parent)
                        //无则使用父容器为父对象
                        parent = kobject_get(&kobj->kset->kobj);

                //添加该kobj到父容器的链表中
                kobj_kset_join(kobj);

                //设置父对象
                kobj->parent = parent;
        }

        pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
                 kobject_name(kobj), kobj, __func__,
                 parent ? kobject_name(parent) : "<NULL>",
                 kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");

        //建立相应的目录
        error = create_dir(kobj);

        if (error) {
                kobj_kset_leave(kobj);
                kobject_put(parent);
                kobj->parent = NULL;

                if (error == -EEXIST)
                        printk(KERN_ERR "%s failed for %s with "
                               "-EEXIST, don't try to register things with "
                               "the same name in the same directory.\n",
                               __func__, kobject_name(kobj));
                else
                        printk(KERN_ERR "%s failed for %s (%d)\n",
                               __func__, kobject_name(kobj), error);
                dump_stack();
        } else
                kobj->state_in_sysfs = 1;

        return error;
}
 

至此bus的目录就建立起来了

 

模型如下

 

接下来是devices,在/drivers/base/core.c里

int __init devices_init(void)
{
        devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
        if (!devices_kset)
                return -ENOMEM;
        return 0;
}
过程和bus的注册一致,我就不复述了~
模型如下

 

然后是platform的注册

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值