这个结构体用于表示某一类对象(用kobject表示)的集合,其定义为:/***kset - a set of kobjects of a specific type, belonging*to a specific subsystem.**All kobjects of a kset should be embedded in an identical *type. This type may have a descriptor, which the kset points*to. This allows there to exist sets of objects of the same*type in different subsystems.**A subsystem does not have to be a list of only one type *of object; multiple ksets can belong to one subsystem. All *ksets of a subsystem share the subsystem's lock.**Each kset can support specific event variables; it can*supress the event generation or add subsystem specific*variables carried with the event.*/struct kset_uevent_ops {int (*filter)(struct kset *kset, struct kobject *kobj);constchar *(*name)(struct kset *kset, struct kobject *kobj);int (*uevent)(struct kset *kset, struct kobject *kobj, char **envp,int num_envp, char *buffer, int buffer_size);};struct kset {struct kobj_type* ktype;struct list_headlist;spinlock_tlist_lock;struct kobjectkobj;struct kset_uevent_ops* uevent_ops;};从list这个成员可以很容易知道每个kset下面都将有许多的kobject。从kobj这个成员也可以猜测出内核是将kset也当成一个对象来看待的,呵呵。通常使用kset_init函数进行此结构体的初始化:/***kset_init - initialize a kset for use*@k:kset */void kset_init(struct kset * k){kobject_init(&k->kobj);INIT_LIST_HEAD(&k->list);spin_lock_init(&k->list_lock);}注意在此并不改变uevent_ops成员的值,此值通常在定义kset的全局变量时初始化(可以初始化为NULL)。Ktype的值同样在全局变量定义时进行初始化,也可以设置为NULL。
此函数用于注册一个kset,其实现在fs/kobject.c中:int subsystem_register(struct kset *s){return kset_register(s);}跟踪kset_register:/***kset_register - initialize and add a kset.*@k:kset.*/int kset_register(struct kset * k){if (!k)return -EINVAL;kset_init(k);return kset_add(k);}挺简单的,先初始化kset结构体,再将它加入到内核中kset的链表中。跟踪kset_add:/***kset_add - add a kset object to the hierarchy.*@k:kset.*/int kset_add(struct kset * k){return kobject_add(&k->kobj);}从这里可以明显看出kset本身的确也是一个kobject。跟踪kobject_add:/***kobject_add - add an object to the hierarchy.*@kobj:object.*/int kobject_add(struct kobject * kobj){return kobject_shadow_add(kobj, NULL);}跟踪kobject_shadow_add:/***kobject_shadow_add - add an object to the hierarchy.*@kobj:object.*@shadow_parent: sysfs directory to add to.*/int kobject_shadow_add(struct kobject * kobj, struct dentry *shadow_parent){int error = 0;struct kobject * parent;if (!(kobj = kobject_get(kobj)))return -ENOENT;if (!kobj->k_name)kobj->k_name = kobj->name;if (!*kobj->k_name) {pr_debug("kobject attempted to be registered with no name!/n");WARN_ON(1);kobject_put(kobj);return -EINVAL;}parent = kobject_get(kobj->parent);pr_debug("kobject %s: registering. parent: %s, set: %s/n",kobject_name(kobj), parent ? kobject_name(parent) : "", kobj->kset ? kobj->kset->kobj.name : "" );if (kobj->kset) {spin_lock(&kobj->kset->list_lock);if (!parent)parent = kobject_get(&kobj->kset->kobj);list_add_tail(&kobj->entry,&kobj->kset->list);spin_unlock(&kobj->kset->list_lock);kobj->parent = parent;}error = create_dir(kobj, shadow_parent);if (error) {/* unlink does the kobject_put() for us */unlink(kobj);kobject_put(parent);/* be noisy on error issues */if (error == -EEXIST)printk(KERN_ERR "kobject_add failed for %s with ""-EEXIST, don't try to register things with ""the same name in the same directory./n",kobject_name(kobj));elseprintk(KERN_ERR "kobject_add failed for %s (%d)/n",kobject_name(kobj), error);dump_stack();}return error;}此时shadow_parent参数为NULL。在此函数中,如果kobject有指定的kset,则将此object添加到kset的对象链表中,如果没有显式指定parent,则取kset做为它的parent。然后调用create_dir函数在sysfs文件系统中创建此kobject的入口。
此函数的定义在lib/kobject.c中:/***populate_dir - populate directory with attributes.*@kobj:object we're working on.**Most subsystems have a set of default attributes that *are associated with an object that registers with them.*This is a helper called during object registration that *loops through the default attributes of the subsystem *and creates attributes files for them in sysfs.**/staticint populate_dir(struct kobject * kobj){struct kobj_type * t = get_ktype(kobj);struct attribute * attr;int error = 0;int i;if (t && t->default_attrs) {