免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3856 | 回复: 3
打印 上一主题 下一主题

利用class动态创建字符设备 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-07-21 09:54 |只看该作者 |倒序浏览
本帖最后由 wmmy2008 于 2010-07-21 09:56 编辑

下面是自己写的一个测试程序, 加载模块后将会在/dev目录下动态创建名为”test”的字符设备文件,并在class目录下生成相关文件.
首先在虚拟机上执行:
[root@FLYING ~]# ps -aux | grep "udev"
root       452  0.0  0.2   2244   608 ?        S<s  00:40   0:00 /sbin/udevd -d
root      2531  0.0  0.2   3980   632 pts/0    R+   00:53   0:00 grep udev
确定udev进程存在, udev会动态创建设备文件.
在加载模块后,我们需要看以下的内容:
[root@FLYING ~]# ls -l /dev/test
crw------- 1 root root 100, 0 2020-03-30 00:56 /dev/test  //在/dev目录下动态生成test字符设备文件

[root@FLYING andy]# pwd
/sys/class/andy           //在class目录下生成andy目录
[root@FLYING andy]# tree
.
|-- classfile        
`-- test
    |-- dev
    |-- devfile
    |-- power
    |   `-- wakeup
    |-- subsystem -> ../../andy
    `-- uevent
3 directories, 5 files

class.rar (1.15 KB, 下载次数: 42)


下面看看代码,我们是怎么实现的:
1 #include <linux/kernel.h>
  2 #include <linux/module.h>
  3 #include <linux/fs.h>
  4 #include <linux/mm.h>
  5 #include <linux/sched.h>
  6 #include <linux/smp_lock.h>
  7 #include <linux/wait.h>
  8 #include <linux/init.h>
  9 #include <linux/delay.h>
10 #include <linux/spinlock.h>
11 #include <linux/device.h>
12
13
14 #define MAJOR_NUM       100
15 static struct class *test_class;
16 static struct device *test_device;
17
18
19 int char_dev_open(struct inode *inode, struct file *file)
20 {
21         printk(KERN_INFO "test open char dev\n");
22         return 0;
23 }
24
25 ssize_t char_dev_read (struct file *file, char __user *buf,
26                         size_t count, loff_t *ppos)
27 {
28         printk(KERN_INFO "test read char dev\n");
29         return 0;
30 }
31
32 static struct file_operations testopt = {
33         .owner = THIS_MODULE,
34         .open = char_dev_open,
35         .read = char_dev_read,
36 };
37
38 static ssize_t classfile_sysfs_show(struct class *class, char *buf)
39 {
40         printk(KERN_INFO "class file show \n");
41         return 0;
42 }
43
44 static ssize_t devfile_sysfs_show(struct device *dev, struct device_attribute *attr,
45                         char *buf)
46 {
47         printk(KERN_INFO "dev file show \n");
48         return 0;
49 }
50
51 static CLASS_ATTR(classfile, S_IRUGO, classfile_sysfs_show, NULL);
52 static DEVICE_ATTR(devfile, S_IRUGO, devfile_sysfs_show,NULL);
53
54 static int __init class_test_init(void)
55 {
56         int err;
57
58         err = register_chrdev(MAJOR_NUM ,"test" ,&testopt);
59         if(err)
60                 goto error;
61
62         test_class = class_create(THIS_MODULE, "andy");
63         if(IS_ERR(test_class)){
64                 err = PTR_ERR(test_class);
65                 goto class_error;
66         }
67
68         test_device = device_create(test_class, NULL ,MKDEV(MAJOR_NUM ,0) ,"test");
69         if(IS_ERR(test_device)){
70                 err = PTR_ERR(test_device);
71                 goto device_error;
72         }
73
74         err = class_create_file(test_class , &class_attr_classfile);
75         if(err)
76                 goto error;
77         err = device_create_file(test_device ,&dev_attr_devfile);
78         if(err)
79                 goto error;
80         return 0;
81
82 device_error:
83         class_destroy(test_class);
84 class_error:
85         unregister_chrdev(MAJOR_NUM ,"test");
86 error:
87         return err;
88 }
89
90 void __exit class_test_exit(void)
91 {
92         unregister_chrdev(MAJOR_NUM ,"test");
93         class_remove_file(test_class, &class_attr_classfile);
94         device_remove_file(test_device,&dev_attr_devfile);
95         device_destroy(test_class,MKDEV(MAJOR_NUM ,0));
96         class_destroy(test_class);
97         return;
98 }
99
100
101 module_init(class_test_init);
102 module_exit(class_test_exit);
103 MODULE_LICENSE("GPL");
104 MODULE_DESCRIPTION("andy wang for sys class device test");

#
# Makefile for the class device test.
#

obj-m           += class_test.o
KERNAL_PATH = /usr/src/linux-2.6.26

default:
        make -C $(KERNAL_PATH) M=$(PWD) modules
clean:
        rm *.o *.ko *.mod.c *.order *.symvers


第58行, 注册一个字符设备”test”
第62,创建一个名字为andy的类class ,此时在/sys/class目录下就生成了andy目录.
第68行,  创建一个名字为“test”的类文件 ,此时就会在andy目录下生成test目录了.
第74行,创建一个类属性文件, 也就是在andy目录下创建一个名为”classfile”的类属性文件.
第77行, 创建一个设备属性文件 ,也就是在test目录下建立一个名为”devfile”的设备属性文件.

那么/dev/test设备文件是如何动态生成的呢?
先看看流程:
device_create()->device_register()->device_add()->kobject_uevent()
最关键的函数就是kobject_uevent()了 , 这个函数将action_string=add,devpath=/class/andy
,subsystem=class等环境变量信息通过netlink发给用户层的udev, 然后udev会找到devpath目录下的dev文件(存放着设备号),然后在/dev目录下动态创建设备文件,所以我们上面要看看udev进程是否存在了。

论坛徽章:
84
每日论坛发贴之星
日期:2015-12-29 06:20:00每日论坛发贴之星
日期:2016-01-16 06:20:00每周论坛发贴之星
日期:2016-01-17 22:22:00程序设计版块每日发帖之星
日期:2016-01-20 06:20:00每日论坛发贴之星
日期:2016-01-20 06:20:00程序设计版块每日发帖之星
日期:2016-01-21 06:20:00每日论坛发贴之星
日期:2016-01-21 06:20:00程序设计版块每日发帖之星
日期:2016-01-23 06:20:00程序设计版块每日发帖之星
日期:2016-01-31 06:20:00数据库技术版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-16 06:20:00程序设计版块每日发帖之星
日期:2016-01-14 06:20:00
2 [报告]
发表于 2010-07-27 20:11 |只看该作者
本帖最后由 yjh777 于 2010-07-27 22:21 编辑

谢谢分享。
发现 2.6 内核API变化真的是太快了

2.6.16
class_device_create()->class_device_register()->class_device_add->kobject_uevent()
class_device_create()接口2.6.25之后没有了。

2.6.18 ~ 2.6.25 ~ now
device_create()->device_register()->device_add()->kobject_uevent()
device_create()->device_create_vargs()->device_register()->device_add()->kobject_uevent()  

2.6.26 ~ 2.6.27 之间还出现了device_create_drvdata
device_create_drvdata()->device_create_vargs()->device_register()->device_add()->kobject_uevent()

论坛徽章:
0
3 [报告]
发表于 2010-07-28 10:01 |只看该作者
接口API变化是有点大,不过基本架构还是没的啥变化...

论坛徽章:
0
4 [报告]
发表于 2012-03-11 12:03 |只看该作者
的确是 kobject_uevent  有了这个广播,
/dev/目录下就会自动生成相应的设备文件
但奇怪的是 我的开发板上怎么ps都看不到有udev进程存在
这是咋回事,
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP