sys之device初始化简单

01int __init devices_init(void)
02{
03 devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
04 if (!devices_kset)
05  return -ENOMEM;
06 dev_kobj = kobject_create_and_add("dev", NULL);
07 if (!dev_kobj)
08  goto dev_kobj_err;
09 sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
10 if (!sysfs_dev_block_kobj)
11  goto block_kobj_err;
12 sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
13 if (!sysfs_dev_char_kobj)
14  goto char_kobj_err;
15
16 return 0;
17
18 char_kobj_err:
19 kobject_put(sysfs_dev_block_kobj);
20 block_kobj_err:
21 kobject_put(dev_kobj);
22 dev_kobj_err:
23 kset_unregister(devices_kset);
24 return -ENOMEM;
25} 

第3行使用kset_create_and_add函数创建一个全局的kset对象,来初始化devices_kset指针。也就是sys目录下创建device目录
第4行如果值为真,说明创建失败,返回。
第6行使用kobject_create_and_add函数创建一个kobject对象,来初始化dev_kobj指针。在sys目录下创建dev目录。
第7行如果if条件为真,说明创建不成功。
第9行创建块设备的kobject对象,其kobject为dev_kobj,也就是在dev目录下创建一个block目录。
第10行如果条件为真,创建不成功,中转到block_koj_err地方处理。
第12行创建字符设备的kobject对象,其kobject为dev_kobj,也就是在dev目录下创建一个char目录。

01struct kset *kset_create_and_add(const char *name,
02     struct kset_uevent_ops *uevent_ops,
03     struct kobject *parent_kobj)
04{
05 struct kset *kset;
06 int error;
07
08 kset = kset_create(name, uevent_ops, parent_kobj);
09 if (!kset)
10  return NULL;
11 error = kset_register(kset);
12 if (error) {
13  kfree(kset);
14  return NULL;
15 }
16 return kset;
17}

这个函数,动态的产生一个kset结构,然后注册它到sysfs文件系统
第8行创建一个kset对象。
第11行注册一个kset对象。

static struct kset *kset_create(const char *name,
    struct kset_uevent_ops *uevent_ops,
    struct kobject *parent_kobj)
01{
02 struct kset *kset;
03
04 kset = kzalloc(sizeof(*kset), GFP_KERNEL);
05 if (!kset)
06  return NULL;
07 kobject_set_name(&kset->kobj, name);
08 kset->uevent_ops = uevent_ops;
09 kset->kobj.parent = parent_kobj;
10
11 /*
12  * The kobject of this kset will have a type of kset_ktype and belong to
13  * no kset itself.  That way we can properly free it when it is
14  * finished being used.
15  */
16 kset->kobj.ktype = &kset_ktype;
17 kset->kobj.kset = NULL;
18
19 return kset;
20}

第4行动态的分配空间给kset指针。
第7行设置kset的名字,其实是通过kset中的kobject对象,来设置名字的。每一个文件夹对应一个kobject对象。
第9行kset对象中的kobject对象的父指针指向parent_kobj,在这里是空指针的,因为它是第一个kset对象,他的kobject也是最顶层的目录
第16行kset对象的kobj.ktype对对象指向kset_ktype.
第17行kset对象的kobj.kset设置为空。

int kset_register(struct kset *k)
01{
02 int err;
03
04 if (!k)
05  return -EINVAL;
06
07 kset_init(k);
08 err = kobject_add_internal(&k->kobj);
09 if (err)
10  return err;
11 kobject_uevent(&k->kobj, KOBJ_ADD);
12 return 0;
13}

第7行使用kset_init函数初始化一个kset对象
第8行增加kset 的kobject对象。

static int kobject_add_internal(struct kobject *kobj)
{
01 int error = 0;
02 struct kobject *parent;
03
04 if (!kobj)
05  return -ENOENT;
06
07 if (!kobj->name || !kobj->name[0]) {
08  WARN(1, "kobject: (%p): attempted to be registered with empty "
09    "name!\n", kobj);
10  return -EINVAL;
11 }
12
13 parent = kobject_get(kobj->parent);
14
15 /* join kset if set, use it as parent if we do not already have one */
16 if (kobj->kset) {
17  if (!parent)
18   parent = kobject_get(&kobj->kset->kobj);
19  kobj_kset_join(kobj);
20  kobj->parent = parent;
21 }
22
23 pr_debug("kobject: '%s' (%p): %s: parent: '%s', set: '%s'\n",
24   kobject_name(kobj), kobj, __func__,
25   parent ? kobject_name(parent) : "<NULL>",
26   kobj->kset ? kobject_name(&kobj->kset->kobj) : "<NULL>");
27
28 error = create_dir(kobj);
29 if (error) {
30  kobj_kset_leave(kobj);
31  kobject_put(parent);
32  kobj->parent = NULL;
33
34  /* be noisy on error issues */
35  if (error == -EEXIST)
36   printk(KERN_ERR "%s failed for %s with "
37          "-EEXIST, don't try to register things with "
38          "the same name in the same directory.\n",
39          __func__, kobject_name(kobj));
40  else
41   printk(KERN_ERR "%s failed for %s (%d)\n",
42          __func__, kobject_name(kobj), error);
43  dump_stack();
44 } else
45  kobj->state_in_sysfs = 1;
46
47 return error;
48}

第13行增加对kobject对象父节点的引用。
第28行创建一个kobject目录
第29-44行如果创建目录出错,减少对父kobject对象的引用。

struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
{
01 struct kobject *kobj;
02 int retval;
03
04 kobj = kobject_create();
05 if (!kobj)
06  return NULL;
07
08 retval = kobject_add(kobj, parent, "%s", name);
09 if (retval) {
10  printk(KERN_WARNING "%s: kobject_add error: %d\n",
11         __func__, retval);
12  kobject_put(kobj);
13  kobj = NULL;
14 }
15 return kobj;
16}

第4行创建一个kobject对象
第8行把这个kobject对象,加入到层次架构中,也就是sysfs文件系统中。

struct kobject *kobject_create(void)
{
01 struct kobject *kobj;
02
03 kobj = kzalloc(sizeof(*kobj), GFP_KERNEL);
04 if (!kobj)
05  return NULL;
06
07 kobject_init(kobj, &dynamic_kobj_ktype);
08 return kobj;
09}

第3行分配kobject对象空间
第7行初始kobject对象

int kobject_add(struct kobject *kobj, struct kobject *parent,
  const char *fmt, ...)
{
01 va_list args;
02 int retval;
03
04 if (!kobj)
05  return -EINVAL;
06
07 if (!kobj->state_initialized) {
08  printk(KERN_ERR "kobject '%s' (%p): tried to add an "
09         "uninitialized object, something is seriously wrong.\n",
10         kobject_name(kobj), kobj);
11  dump_stack();
12  return -EINVAL;
13 }
14 va_start(args, fmt);
15 retval = kobject_add_varg(kobj, parent, fmt, args);
16 va_end(args);
17
18 return retval;
19}

kobject对象的名字会被加到kobject的层次树中。如果出错的话,会减少对kobject的引用。

下面的函数分别是增加char和block的目录。和dev目录的增加是类似的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值