本文中的源码均来自linux内核3.14.3版本/lib/kobject.c文件
/**
* kset_register - 初始化并添加一个kset
* @k: kset.
*/
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 - 初始化一个kset
* @k: kset
*/
void kset_init(struct kset *k)
{
kobject_init_internal(&k->kobj);
INIT_LIST_HEAD(&k->list);
spin_lock_init(&k->list_lock);
}
static void kobject_init_internal(struct kobject *kobj)
{
if (!kobj)
return;
kref_init(&kobj->kref);//kref是引用计数,该struct仅有一个成员,就是atomic_t refcount,这里把他初始化为1
INIT_LIST_HEAD(&kobj->entry);//entry是一个struct list_head,这里把entry的next和prev均指向entry
kobj->state_in_sysfs = 0; //不在sysfs中显示
kobj->state_add_uevent_sent = 0;
kobj->state_remove_uevent_sent = 0;
kobj->state_initialized = 1;
}
static int kobject_add_internal(struct kobject *kobj)
{
int error = 0;
struct kobject *parent;
if (!kobj)
return -ENOENT;
if (!kobj->name || !kobj->name[0]) {
WARN(1, "kobject: (%p): attempted to be registered with empty name!\n", kobj);
return -EINVAL;
}
parent = kobject_get(kobj->parent);//parent的引用计数加一
/* join kset if set, use it as parent if we do not already have one */
/* 把kobject加入kset, 如果没有parent的话,就把它作为parent*/
if (kobj->kset) {
if (!parent)
parent = kobject_get(&kobj->kset->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;
/* be noisy on error issues */
if (error == -EEXIST)
WARN(1, "%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
WARN(1, "%s failed for %s (error: %d parent: %s)\n", __func__, kobject_name(kobj), error,
parent ? kobject_name(parent) : "'none'");
} else
kobj->state_in_sysfs = 1;
return error;
}
/**
* kobject_get - object增加计数
* @kobj: object.
*/
struct kobject *kobject_get(struct kobject *kobj)
{
if (kobj)
kref_get(&kobj->kref);
return kobj;
}
我很想在这死磕一下,因为后面是继续调用原子操作来增加该计数,而我对原子操作只有概念上的认识,没有清晰的理解,不够看起来原子操作还挺麻烦的,这里就先放下了
static int create_dir(struct kobject *kobj)
{
const struct kobj_ns_type_operations *ops;
int error;
error = sysfs_create_dir_ns(kobj, kobject_namespace(kobj));
if (error)
return error;
error = populate_dir(kobj);
if (error) {
sysfs_remove_dir(kobj);
return error;
}
/*
* @kobj->sd 可能会被一个原始对象删除,保留一个备份索引
* 保证它可以持续到@kobj 释放。
*/
sysfs_get(kobj->sd);
/*
* 如果@kobj有ns_ops, 它的子对象需要用命名空间tags过滤,在@kobj->sd
* 中使能命名空间支持。
*/
ops = kobj_child_ns_ops(kobj);
if (ops) {
BUG_ON(ops->type <= KOBJ_NS_TYPE_NONE);
BUG_ON(ops->type >= KOBJ_NS_TYPES);
BUG_ON(!kobj_ns_type_registered(ops->type));
kernfs_enable_ns(kobj->sd);
}
return 0;
}