本文源码均来自linux 3.14.3版本/lib/kobject.c文件
/**
* kobject_create_and_add - 动态创建一个kobject结构并注册到sysfs
*
* @name: kobject的名称
* @parent: kobject的parent kobject of this kobject, 如果有的话
*
* 该方法动态创建一个kobject结构并注册到sysfs。当你完成该结构
* 之后. 调用kobject_put(),这样该结构在不再使用时将会动态的释放。
*
* 如果该kobject无法被创建,将会返回NULL。
*/
struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{
struct kobject *kobj;
int retval;
kobj = kobject_create();
if (!kobj)
return NULL;
retval = kobject_add(kobj, parent, "%s", name);
if (retval) {
printk(KERN_WARNING "%s: kobject_add error: %d\n", __func__, retval);
kobject_put(kobj);
kobj = NULL;
}
return kobj;
}
/**
* kobject_create - 动态创建一个kobject结构
*
* 动态创建一个kobject结构,并将其设置为一个带默认释放方法的
* 动态的kobject。
*
* 如果无法创建kobject,将会返回NULL。从这里返回的kobject 结构释放
* 必须调用kobject_put() 方法而不是kfree(),因为kobject_init()已经被调用
* 过了。
*/
struct kobject *kobject_create(void)
{
struct kobject *kobj;
kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
if (!kobj)
return NULL;
kobject_init(kobj, &dynamic_kobj_ktype);
return kobj;
}
/**
* kobject_init - 初始化一个kobject结构
* @kobj: 指向要初始化的kobject的指针
* @ktype: 指向该kobject 的ktype的指针
*
* 该方法会正确的初始化一个kobject来保证它可以被传递给kobject_add()
* 调用.
*
* 该功能被调用后,kobject必须通过调用kobject_put()来清理,而不是直接
* 调用kfree,来保证所有的内存都可以被正确的清理。
*/
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);
kobj->state_in_sysfs = 0;
kobj->state_add_uevent_sent = 0;
kobj->state_remove_uevent_sent = 0;
kobj->state_initialized = 1;
}
/**
* kobject_add - kobject添加主方法
* @kobj: 要添加的kobject
* @parent: 指向父kobject的指针
* @fmt: kobject带的名称格式
*
* 本方法中会设置kobject名称并添加到kobject阶层。
*
* 如果设置了@parent, 那么@kobj的parent将会被设置为它.
* 如果 @parent为空, 那么该@kobj的 parent会被设置为与该kobject
* 相关联的. 如果没有kset分配给这个kobject,那么该kobject会放在
* sysfs的根目录。
*
* 如果该方法返回错误,必须调用 kobject_put()来正确的清理该object
* 相关联的内存。
* 在任何情况下都不要直接通过调用to kfree()来直接释放传递给该方法
* 的kobject,那样会导致内存泄露。
*
* 注意,该调用不会创建"add" uevent, 调用方需要为该object设置好所有
* 必要的sysfs文件,然后再调用带UEVENT_ADD 参数的kobject_uevent()
* 来保证用户控件可以正确的收到该kobject创建的通知。
*/
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;
retval = kobject_set_name_vargs(kobj, fmt, vargs);
if (retval) {
printk(KERN_ERR "kobject: can not set name properly!\n");
return retval;
}
kobj->parent = parent;
return kobject_add_internal(kobj);
}
/**
* kobject_set_name_vargs - 设置一个kobject的名称
* @kobj: 要设置名称的kobject
* @fmt: 用来构建名称的字符串格式
* @vargs: 构建字符串的参数
*/
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;
kobj->name = kvasprintf(GFP_KERNEL, fmt, vargs);
if (!kobj->name) {
kobj->name = old_name;
return -ENOMEM;
}
/* ewww... some of these buggers have '/' in the name ... */
while ((s = strchr(kobj->name, '/')))
s[0] = '!';
kfree(old_name);
return 0;
}
kobject_add_internal源码前面已经粘贴过了,这里就不再继续粘贴了