/*struct kobj_type的声明*/ struct kobj_type { /*用于释放kobject*/ void (*release)(struct kobject *kobj); /*sys的操作表*/ const struct sysfs_ops *sys_ops; /*内核对象的属性,对应于sys文件系统的文件*/ struct attribute **default_attrs; }; struct kobj_attribute { struct attribute attr; ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr, char *buf); ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); }; struct attribute { const char *name; struct module *owner; mode_t mode; } /** * kobject初始化 **/ void kobject_init(struct kobject *kobj, struct kobj_type *ktype) { char *err_str; /*参数检查*/ if (!kobj) { err_str = "invalid kobject pointer!"; goto error; } if (!ktype) { err_str = "must have a ktype to be initialized properly!\n"; goto error; } /*不能重复初始化*/ if (kobj->state_initialized) { /* do not error out as sometimes we can recover */ printk(KERN_ERR "kobject (%p): tried to init an initialized " "object, something is seriously wrong.\n", kobj); dump_stack(); } /*初始化*/ kobject_init_internal(kobj); /*设置类型*/ kobj->ktype = ktype; return; error: printk(KERN_ERR "kobject (%p): %s\n", kobj, err_str); dump_stack(); } static void kobject_init_internal(struct kobject *kobj) { /*参数检查*/ if (!kobj) return; /*初始化引用计数*/ kref_init(&kobj->kref); /*初始化链入链表的节点*/ INIT_LIST_HEAD(&kobj->entry); /*初始化kobject的状态*/ kobj->state_in_sysfs = 0; kobj->state_add_uevent_sent = 0; kobj->state_remove_uevent_sent = 0; kobj->state_initialized = 1; } /*添加到sys文件系统*/ 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; } static int kobject_add_varg(struct kobject *kobj, struct kobject *parent, const char *fmt, va_list vargs) { int retval; /*设置kobject的名字*/ retval = kobject_set_name_vargs(kobj, fmt, vargs); if (retval) { printk(KERN_ERR "kobject: can not set name properly!\n"); return retval; } /*设置父kobj*/ kobj->parent = parent; /*来,开始添加*/ return kobject_add_internal(kobj); } /** * kobject_set_name_vargs - Set the name of an kobject * @kobj: struct kobject to set the name of * @fmt: format string used to build the name * @vargs: vargs to format the string. */ int kobject_set_name_vargs(struct kobject *kobj, const char *fmt, va_list vargs) { const char *old_name = kobj->name; char *s; /*参数检查*/ if (kobj->name && !fmt) return 0; /*char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap),合成字符串*/ kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs); /*创建失败*/ if (!kobj->name) return -ENOMEM; /* ewww... some of these buggers have '/' in the name ... */ /*替换路径中的'/'为'!',你懂的*/ while ((s = strchr(kobj->name, '/'))) s[0] = '!'; /*释放老的名字*/ kfree(old_name); return 0; } 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; } /*增加父kobject的引用计数*/ parent = kobject_get(kobj->parent); /* join kset if set, use it as parent if we do not already have one */ if (kobj->kset) { if (!parent) parent = kobject_get(&kobj->kset->kobj); //添加到kset 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) 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; } static int create_dir(struct kobject *kobj) { int error = 0; if (kobject_name(kobj)) { //创建kobject对应的目录 error = sysfs_create_dir(kobj); if (!error) { //创建kobj对应属性的文件 error = populate_dir(kobj); if (error) //创建失败,进行回滚 sysfs_remove_dir(kobj); } } return error; }