int __init classes_init(void)
{
class_kset = kset_create_and_add("class", NULL, NULL);//parent_kobj为NULL,"class"目录将创建到sysfs_root-sysfs的根'/'下面.
if (!class_kset)
return -ENOMEM;
//到这里/sys/class目录就已经创建成功了,并且当sysfs被mount到/sys目录之后,/sys/class就可以通过ls可见了[luther.gliethttp]
/* ick, this is ugly, the things we go through to keep from showing up
* in sysfs... */
kset_init(&class_obj_subsys);
kobject_set_name(&class_obj_subsys.kobj, "class_obj");
if (!class_obj_subsys.kobj.parent)
class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
return 0;
}
struct kset *kset_create_and_add(const char *name,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
int error;
kset = kset_create(name, uevent_ops, parent_kobj);//创建kset
if (!kset)
return NULL;
error = kset_register(kset);
if (error) {
kfree(kset);
return NULL;
}
return kset;
}
static struct kset *kset_create(const char *name,
struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
kset = kzalloc(sizeof(*kset), GFP_KERNEL);//申请内存空间
if (!kset)
return NULL;
kobject_set_name(&kset->kobj, name);//kmalloc内存,然后拷贝name,最后kobj->name = name;
kset->uevent_ops = uevent_ops;//uevent处理函数
kset->kobj.parent = parent_kobj;//
/*
* The kobject of this kset will have a type of kset_ktype and belong to
* no kset itself. That way we can properly free it when it is
* finished being used.
*/
kset->kobj.ktype = &kset_ktype;//包含该kset管理的所有属性文件的read和write通用实现函数,show和store
kset->kobj.kset = NULL;//该kset就是父,不再有其他kset来管理本kset
return kset;
}
========================================
int kobject_set_name(struct kobject *kobj, const char *fmt, ...)
{
va_list args;
int retval;
va_start(args, fmt);
retval = kobject_set_name_vargs(kobj, fmt, args);
va_end(args);
return retval;
}
static int kobject_set_name_vargs(struct kobject *kobj, const char *fmt,
va_list vargs)
{
va_list aq;
char *name;
va_copy(aq, vargs);
name = kvasprintf(GFP_KERNEL, fmt, vargs);//kmalloc之后赋值,返回到name指针
va_end(aq);
if (!name)
return -ENOMEM;
/* Free the old name, if necessary. */
kfree(kobj->name);//释放原有的name,如果有
/* Now, set the new name */
kobj->name = name;//设置name
return 0;
}
char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)
{
unsigned int len;
char *p;
va_list aq;
va_copy(aq, ap);
len = vsnprintf(NULL, 0, fmt, aq);