kset总是在sysfs中出现,一旦设置了kset并把它添加到系统中,就会在sysfs中创建一个目录。kset中的每一个kobject成员都会在sysfs中表述。
kset定义:
/**
* struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
*
* A kset defines a group of kobjects. They can be individually
* different "types" but overall these kobjects all want to be grouped
* together and operated on in the same manner. ksets are used to
* define the attribute callbacks and other common events that happen to
* a kobject.
*
* @list: the list of all kobjects for this kset
* @list_lock: a lock for iterating over the kobjects
* @kobj: the embedded kobject for this kset (recursion, isn't it fun...)
* @uevent_ops: the set of uevent operations for this kset. These are
* called whenever a kobject has something happen to it so that the kset
* can add new environment variables, or filter out the uevents if so
* desired.
*/
struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
const struct kset_uevent_ops *uevent_ops;
};
创建一个对象kobject时,通常会把kobject添加到kset中去,这个过程分2个步骤:
1. 先把kobject的kset成员,指向目的kset,然后运行kobject_add().
/**
* kobject_add - the main kobject add function
* @kobj: the kobject to add
* @parent: pointer to the parent of the kobject.
* @fmt: format to name the kobject with.
*
* The kobject name is set and added to the kobject hierarchy in this
* function.
*
* If @parent is set, then the parent of the @kobj will be set to it.
* If @parent is NULL, then the parent of the @kobj will be set to the
* kobject associted with the kset assigned to this kobject. If no kset
* is assigned to the kobject, then the kobject will be located in the
* root of the sysfs tree.
*
* If this function returns an error, kobject_put() must be called to
* properly clean up the memory associated with the object.
* Under no instance should the kobject that is passed to this function
* be directly freed with a call to kfree(), that can leak memory.
*
* Note, no "add" uevent will be created with this call, the caller should set
* up all of the necessary sysfs files for the object and then call
* kobject_uevent() with the UEVENT_ADD parameter to ensure that
* userspace is properly notified of this kobject's creation.
*/
int kobject_add(struct kobject *kobj, struct kobject *parent,
const char *fmt, ...)
{
va_list args;
int retval;
if (!kobj)
return -EINVAL;
if (!kobj->state_initialized) {
printk(KERN_ERR "kobject '%s' (%p): tried to add an "
"uninitialized object, something is seriously wrong.\n",
kobject_name(kobj), kobj);
dump_stack();
return -EINVAL;
}
va_start(args, fmt);
retval = kobject_add_varg(kobj, parent, fmt, args);
va_end(args);
return retval;
}
EXPORT_SYMBOL(kobject_add);
2. kobject_del(): 把kobject从kset中删除,以清除引用计数。
/**
* kobject_del - unlink kobject from hierarchy.
* @kobj: object.
*/
void kobject_del(struct kobject *kobj)
{
if (!kobj)
return;
sysfs_remove_dir(kobj);
kobj->state_in_sysfs = 0;
kobj_kset_leave(kobj);
kobject_put(kobj->parent); //清除引用记数
kobj->parent = NULL;
}
3. kset操作:kset有与kobject相似的初始化和设置接口:
a. kset_init():
/**
* kset_init - initialize a kset for use
* @k: kset
*/
void kset_init(struct kset*k)
{
kobject_init_internal(&k->kobj);
INIT_LIST_HEAD(&k->list);
spin_lock_init(&k->list_lock);
}
b. kset_register()/ kset_unregister():
/**
* kset_register - initialize and add a 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_unregister - remove a kset.
* @k: kset.
*/
void kset_unregister(struct kset *k)
{
if (!k)
return;
kobject_put(&k->kobj);
}
c. kset的引用计数管理:kset_get() / kset_put()
static inline struct kset *kset_get(struct kset *k)
{
return k ? to_kset(kobject_get(&k->kobj)) : NULL;
}
static inline void kset_put(struct kset *k)
{
kobject_put(&k->kobj);
}
d. kset的名字,保存在内嵌的kobject中。即 kset->kobj的name 。
e. kset也有一个指针指向kobj_type结构,用来描述kobject。典型应用中,会把kobject中的ktype成员设置为null,因为kset中的ktype成员是实际上被使用的成员。
f. kset中包含了一个子系统指针 subsys. 子系统通常显示在sysfs分层结构中的顶层。