本文介绍linux中class_create和class_register的相关使用方法
内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
如下表:
示例一,通过class_create()、class_destroy()去注册和注销/sys/class/my_char_dev
代码如下:
1 #include <linux/module.h>
2 #include <linux/init.h>
3 #include <linux/device.h>
4
5structclass *mem_class;
6
7staticint __init class_create_destroy_init(void)
8{
9 // class_create动态创建设备的逻辑类,并完成部分字段的初始化,然后将其添加到内核中。创建的逻辑类位于/sys/class/。
10 //参数:
11 // owner,拥有者。一般赋值为THIS_MODULE。
12 // name,创建的逻辑类的名称。
13 mem_class = class_create(THIS_MODULE,"my_char_dev");
14 if (mem_class==NULL)
15 {
16 printk("<0>create class failed!\n");
17 return -1;
18 }
19
20 return0;
21}
22
23staticvoid __exit class_create_destroy_exit(void)
24{
25 if (mem_class != NULL)
26 {
27 class_destroy(mem_class);
28 mem_class = NULL;
29 }
30
31}
32
33module_init(class_create_destroy_init);
34module_exit(class_create_destroy_exit);
35
36 MODULE_LICENSE("GPL");
示例二,通过class_register()、class_unregister()去注册和注销/sys/class/my_char_dev
代码如下:
1 #include <linux/module.h>
2 #include <linux/init.h>
3 #include <linux/device.h>
4 #include <linux/slab.h>
5
6#define CLASS_NAME "my_char_dev"
7structclass *mem_class;
8
9staticvoid class_create_release (structclass *cls)
10{
11 printk("%s\n", __func__ );
12 kfree(cls);
13}
14
15staticint __init class_create_destroy_init(void)
16{
17 printk("%s\n", __func__);
18
19 int ret;
20
21 //申请class结构体内存
22 mem_class = kzalloc(sizeof(*mem_class), GFP_KERNEL);
23 if (mem_class == NULL)
24 {
25 printk("create memclass failed!\n");
26 return -1;
27 }
28 printk("create memclass success\n");
29
30 mem_class->name =CLASS_NAME;
31 mem_class->owner =THIS_MODULE;
32 //注销时class时的回调函数,在此回调函数中释放之前所分配的class结构体内存
33 mem_class->class_release = class_create_release;
34
35 //将class注册到内核中,同时会在/sys/class/下创建class对应的节点
36 int retval =class_register(mem_class);
37 if (ret)
38 {
39 printk("class_registerfailed!\n");
40 kfree(mem_class);
41 return -1;
42 }
43 printk("class_registersuccess\n");
44
45
46 return0;
47}
48
49staticvoid __exit class_create_destroy_exit(void)
50{
51 printk("%s\n", __func__);
52
53 if (mem_class != NULL)
54 {
55 class_unregister(mem_class);
56 mem_class = NULL;
57 }
58}
59
60module_init(class_create_destroy_init);
61module_exit(class_create_destroy_exit);
62
63 MODULE_LICENSE("GPL");
附录一,class_create()和class_register()对比
实际上,示例一和示例二是等价的。具体的可以通过查看class_create()和class_register()、class_destroy()和class_unregister()的源码去验证。
class_register()的代码如下:
1//将class注册到/sys/class/中
2#define class_register(class) \
3({ \
4 staticstruct lock_class_key __key; \
5 __class_register(class, &__key); \
6 })
class_register()是通过调用__class_register()来注册到sysfs中的。
__class_register()的代码如下:
1int __class_register(structclass *cls, struct lock_class_key *key)
2{
3 structclass_private *cp;
4 interror;
5
6 pr_debug("device class '%s': registering\n", cls->name);
7
8 cp = kzalloc(sizeof(*cp),GFP_KERNEL);
9 if (!cp)
10 return -ENOMEM;
11 klist_init(&cp->class_devices,klist_class_dev_get, klist_class_dev_put);
12 INIT_LIST_HEAD(&cp->class_interfaces);
13 kset_init(&cp->class_dirs);
14 __mutex_init(&cp->class_mutex,"struct class mutex", key);
15 error = kobject_set_name(&cp->class_subsys.kobj,"%s", cls->name);
16 if (error) {
17 kfree(cp);
18 return error;
19 }
20
21 /* set the default /sys/dev directory fordevices of this class */
22 if (!cls->dev_kobj)
23 cls->dev_kobj =sysfs_dev_char_kobj;
24
25#if defined(CONFIG_SYSFS_DEPRECATED)&& defined(CONFIG_BLOCK)
26 /* let the block class directory show up inthe root of sysfs */
27 if (cls != &block_class)
28 cp->class_subsys.kobj.kset = class_kset;
29#else
30 cp->class_subsys.kobj.kset = class_kset;
31#endif
32 cp->class_subsys.kobj.ktype = &class_ktype;
33 cp->class = cls;
34 cls->p = cp;
35
36 //将class注册到内核中
37 error = kset_register(&cp->class_subsys);
38 if (error) {
39 kfree(cp);
40 return error;
41 }
42 error =add_class_attrs(class_get(cls));
43 class_put(cls);
44 return error;
45 }
class_unregister()的代码如下:
1void class_unregister(structclass *cls)
2{
3 pr_debug("deviceclass '%s': unregistering\n",cls->name);
4 remove_class_attrs(cls);
5 //将class从内核中注销
6 kset_unregister(&cls->p->class_subsys);
7 }
下面,我们查看class_create()、class_destroy()的相关代码。
class_create()的代码如下:
1#define class_create(owner, name) \
2({ \
3 staticstruct lock_class_key __key; \
4 __class_create(owner, name, &__key); \
5 })
class_create()是通过调用__class_create()注册到内核中的。
__class_create()的代码如下:
1structclass *__class_create(structmodule *owner, constchar *name,
2 struct lock_class_key *key)
3{
4 structclass *cls;
5 intretval;
6
7 //分配class结构体
8 cls = kzalloc(sizeof(*cls),GFP_KERNEL);
9 if (!cls) {
10 retval = -ENOMEM;
11 goto error;
12 }
13
14 cls->name = name;
15 cls->owner =owner;
16 // class对应的释放函数,在class从内核中注销时会执行该函数
17 cls->class_release =class_create_release;
18
19 //通过调用__class_register()将class注册到内核中
20 retval =__class_register(cls, key);
21 if (retval)
22 goto error;
23
24 return cls;
25
26error:
27 kfree(cls);
28 return ERR_PTR(retval);
29 }
class_create_release的代码如下:
1staticvoid class_create_release(structclass *cls)
2{
3 pr_debug("%s calledfor %s\n", __func__,cls->name);
4 //释放class结构体
5 kfree(cls);
6 }
实际上,__class_create()是通过调用__class_register()注册到sysfs中的!所以,本质上,class_create()和class_register()的作用是类似的。
class_destroy()的代码如下:
1void class_destroy(structclass *cls)
2{
3 if ((cls == NULL) ||(IS_ERR(cls)))
4 return;
5 //调用class_unregister()将class从内核中注销
6 class_unregister(cls);
7 }
实际上,class_destroy()是通过调用class_unregister()实现的。