http://blog.csdn.net/angle_birds/article/details/16802099

本文介绍linux中class_create和class_register的相关使用方法

1 class结构体介绍

内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建 好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。

2 class相关API说明

如下表:

3 class_create()使用示例

示例一,通过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
5 struct class *mem_class;
6
7 static int __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 return 0;
21 }
22
23 static void __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
33 module_init(class_create_destroy_init);
34 module_exit(class_create_destroy_exit);
35
36 MODULE_LICENSE("GPL");

4 class_register()使用示例

示例二,通过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"
7 struct class *mem_class;
8
9 static void class_create_release (struct class *cls)
10 {
11 printk("%s\n", __func__ );
12 kfree(cls);
13 }
14
15 static int __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 mem class failed!\n");
26 return -1;
27 }
28 printk("create mem class 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_register failed!\n");
40 kfree(mem_class);
41 return -1;
42 }
43 printk("class_register success\n");
44
45
46 return 0;
47 }
48
49 static void __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
60 module_init(class_create_destroy_init);
61 module_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 static struct lock_class_key __key; \
5 __class_register(class, &__key); \
6 })

class_register()是通过调用__class_register()来注册到sysfs中的。

__class_register()的代码如下:

 1 int __class_register(struct class *cls, struct lock_class_key *key)
2 {
3 struct class_private *cp;
4 int error;
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 for devices 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 in the 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()的代码如下:

1 void class_unregister(struct class *cls)
2 {
3 pr_debug("device class '%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 static struct lock_class_key __key; \
4 __class_create(owner, name, &__key); \
5 })

class_create()是通过调用__class_create()注册到内核中的。

__class_create()的代码如下:

 1 struct class *__class_create(struct module *owner, const char *name,
2 struct lock_class_key *key)
3 {
4 struct class *cls;
5 int retval;
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
26 error:
27 kfree(cls);
28 return ERR_PTR(retval);
29 }

class_create_release的代码如下:

1 static void class_create_release(struct class *cls)
2 {
3 pr_debug("%s called for %s\n", __func__, cls->name);
4 // 释放class结构体
5 kfree(cls);
6 }

实际上,__class_create()是通过调用__class_register()注册到sysfs中的!所以,本质上,class_create()和class_register()的作用是类似的。

class_destroy()的代码如下:

1 void class_destroy(struct class *cls)
2 {
3 if ((cls == NULL) || (IS_ERR(cls)))
4 return;
5 // 调用class_unregister()将class从内核中注销
6 class_unregister(cls);
7 }

实际上,class_destroy()是通过调用class_unregister()实现的。

linux中class_create和class_register说明的更多相关文章

  1. 在 Linux 中安装 Oracle JDK 8 以及 JVM 的类加载机制

    参考资料 该文中的内容来源于 Oracle 的官方文档 Java SE Tools Reference .Oracle 在 Java 方面的文档是非常完善的.对 Java 8 感兴趣的朋友,可以直接找 ...

  2. Linux中find常见用法示例

    ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \; find命令的参数: pathname: find命 ...

  3. Linux中检索文件

    1 , Use locate command It is a fast way to find the files location, but if a file just created ,it w ...

  4. 如何在Linux中搭建禅道8.4.1(httpd+php+mysql)

    1.安装httpd 命令:yum install httpd 然后一路y即可 2.安装php 命令:yum install php   3.安装php-mysql 命令:yum install php ...

  5. Linux中的用户和用户组

      在Linux中,有三种用户: Root 用户:也称为超级用户,对系统拥有完全的控制权限.超级用户可以不受限制的运行任何命令.Root 用户可以看做是系统管理员. 系统用户:系统用户是Linux运行 ...

  6. linux中shell变量$#,$@,$0,$1,$2的含义解释

    linux中shell变量$#,$@,$0,$1,$2的含义解释: 变量说明: $$ Shell本身的PID(ProcessID) $! Shell最后运行的后台Process的PID $? 最后运行 ...

  7. 在linux中设置静态ip地址

    在linux中设置静态ip地址1.在终端中输入:vi /etc/sysconfig/network-scripts/ifcfg-eth0 2.开始编辑,填写ip地址.子网掩码.网关.DNS等[root ...

  8. windows和linux中搭建python集成开发环境IDE——如何设置多个python环境

    本系列分为两篇: 1.[转]windows和linux中搭建python集成开发环境IDE 2.[转]linux和windows下安装python集成开发环境及其python包 3.windows和l ...

  9. linux 中部署ant编译的包中缺少问题

    今天遇到在window上部署ant编译的包,能运行正常,但部署在linux中出现跳不进jsp中,出现404问题,后来经过排查在jsp中<%@taglib prefix="c" ...

随机推荐

  1. java访问webservice服务(二)

    欢迎转载,出处http://www.cnblogs.com/shizhongtao/p/3433679.html 利用cxf的框架实现 import javax.xml.namespace.QName ...

  2. uva247 - Calling Circles(传递闭包+DFS)

    题意:两人相互打电话(直接或间接),则在一个电话圈.即a给b打电话,b给c打电话,则a给c间接打电话. 注意:1.注意标记.2.注意输出格式. #include<iostream> #in ...

  3. Base64编码原理与应用

    本文内容转自网络,如需详细内容,请参考相关网址. http://my.oschina.net/goal/blog/201032 代码参考:http://blog.csdn.net/prsniper/a ...

  4. java学习笔记_MIDI_GUI

    import javax.sound.midi.*; import javax.swing.*; import java.awt.event.*; import java.awt.*; class M ...

  5. DDL_数据库模式定义语言

    2014年11月22日 15:53:24 DDL 定义  define 概念:是用于描述数据库中要存储的现实世界实体的语言.一个数据库模式包含该数据库中所有实体的描述定义.               ...

  6. C#源码大汇总

    C#高仿QQ2013可在广域网部署聊天系统GG叽叽 动态显示硬盘分区容量饼图 自定义ProgressBar控件高仿Win8进度条 多皮肤精美在线QQ悬浮客服插件 jQuery仿天猫首页多格焦点图片轮播 ...

  7. Unity学习笔记(2):注册映射

    在上一篇文章中(认识Unity)中概要介绍了Unity和Ioc,本节主要介绍IoC中的注册映射,并使用代码和配置文件两种方式进行说明. 定义依赖注入相关信息 定义ILogger接口 public in ...

  8. mac OS X下PhpStorm+MAMP PRO+Xdebug+FireFox集成开发和断点调试环境配置

    一.环境及软件 1.macbook pro 2.Phpstorm 3.MAMP PRO 4.FireFox 二.环境搭建 1.PhpStorm导入项目 下载PhpStorm并安装,网上随便找个注册码即 ...

  9. 解决Win7系统安装时“安装程序无法定位现有 系统分区,也无法创建新的系统分区”提示

    第一步:U盘启动装系统时,格式化主分区的内容后出现上面的问题 第二步:重启机器,通过U 盘启动.进入win pe系统. 第三步:把windows 7的ISO镜像解压到电脑的非系统盘的其他硬盘上.如D: ...

  10. 【C++】GacLib——ListView.ViewSwitching

    http://www.gaclib.net/Demos/Controls.ListView.ViewSwitching/Demo.html#FILESYSTEMINFORMATION_H