首先是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的注册
本文详细解析了Linux内核中的设备模型注册流程,包括bus、devices及platform的注册过程。通过对关键函数如kset_create_and_add和kobject_add_internal的分析,揭示了设备模型在内核中的组织方式。
5

被折叠的 条评论
为什么被折叠?



