1:什么是misc驱动模型?
2:为什么要有misc驱动模型?
3:misc驱动模型的代码实现
4:misc驱动模型实战
参考:
http://blog.csdn.net/yicao821/article/details/6785738
http://www.thinksaas.cn/topics/0/507/507168.html
http://www.cnblogs.com/fellow1988/p/6235080.html
https://www.zhihu.com/question/21508904
http://www.cnblogs.com/snake-hand/p/3212483.html
http://blog.csdn.net/chenlong12580/article/details/7339127
--------------------------------------------------------------------------------------------------------------------------------------------------------------
1:什么是misc驱动模型
Linux包含了许多的设备驱动类型,而不管分类有多细,总会有些漏网的,这就是我们经常说到的“其他的”等等。
在Linux里面,把无法归类的五花八门的设备定义为混杂设备(用miscdevice结构体来描述)。Linux/内核所提供的miscdevice有很强的包容性。如NVRAM,看门狗,DS1286等实时时钟,字符LCD,AMD 768随机数发生器。
miscdevice共享一个主设备号MISC_MAJOR(10),但此设备号不同,所有的miscdevice设备形成一个链表,对设备访问时内核根据次设备号查找对应的 miscdevice设备,然后调用其中的file_operations结构体中注册的文件操作接口进程操作。
2:为什么要有misc驱动模型
第一,节省主设备号:
使用普通字符设备,不管该驱动的主设备号是静态还是动态分配,都会消耗一个主设备号,这太浪费了。而且如果你的这个驱动最终会提交到内核主线版本上的话,需要申请一个专门的主设备号,这也麻烦。
如果使用misc驱动的话就好多了。因为内核中已经为misc驱动分配了一个主设备号。当系统中拥有多个misc设备驱动时,那么它们的主设备号相同,而用子设备号来区分它们。
第二,使用简单:
有时候驱动开发人员需要开发一个功能较简单的字符设备驱动,导出接口让用户空间程序方便地控制硬件,只需要使用misc子系统提供的接口即可快速地创建一个misc设备驱动。
当使用普通的字符设备驱动时,如果开发人员需要导出操作接口给用户空间的话,需要自己去注册字符驱动,并创建字符设备class以自动在/dev下生成设备节点,相对麻烦一点。而misc驱动则无需考虑这些,基本上只需要把一些基本信息通过struct miscdevice交给misc_register()去处理即可。
本质上misc驱动也是一个字符设备驱动,可能相对特殊一点而已。在drivers/char/misc.c的misc驱动初始化函数misc_init()中实际上使用了MISC_MAJOR(主设备号为10)并调用register_chrdev()去注册了一个字符设备驱动。同时也创建了一个misc_class,使得最后可自动在/dev下自动生成一个主设备号为10的字符设备。总的来讲,如果使用misc驱动可以满足要求的话,那么这可以为开发人员剩下不少麻烦。
所以说misc驱动模型让我们很简单的在底层实现了字符设备驱动,并且在在应用层给予了一定的接口,节省了主设备号;其实就相当于一个杂货铺,乱七八糟的字符设备驱动模型都可以往里面堆。
3:驱动模型代码实现:
misc驱动的实现代码在driver/char/misc.c目录下,
misc_init函数:
1 static int __init misc_init(void)
2 {
3 int err;
4
5 #ifdef CONFIG_PROC_FS
6 proc_create('misc', 0, NULL, &misc_proc_fops);
7 #endif
8 misc_class = class_create(THIS_MODULE, 'misc');
9 err = PTR_ERR(misc_class);
10 if (IS_ERR(misc_class))
11 goto fail_remove;
12
13 err = -EIO;
14 if (register_chrdev(MISC_MAJOR,'misc',&misc_fops))
15 goto fail_printk;
16 misc_class->devnode = misc_devnode;
17 return 0;
18
19 fail_printk:
20 printk('unable to get major %d for misc devicesn', MISC_MAJOR);
21 class_destroy(misc_class);
22 fail_remove:
23 remove_proc_entry('misc', NULL);
24 return err;
25 }
26 subsys_initcall(misc_init);
misc_init
class_create 创建了一个名为misc的类
register_chrdev(MISC_MAJOR,'misc',&misc_fops) 使用register_chrdev注册了一个字符设备驱动,主设备号为MISC_MAJOR(10);
1 static const struct file_operations misc_fops = {
2 .owner = THIS_MODULE,
3 .open = misc_open,
4 };
misc类型驱动提供了一个统一.open函数misc_open函数;
misc_open 这个函数的实质是通过inode找到misc类的次设备号minor,然后在通过次设备号和misc链表的次设备号进行匹配,匹配好以后取出
1 static int misc_open(struct inode * inode, struct file * file)
2 {
3 int minor = iminor(inode);
4 struct miscdevice *c;
5 int err = -ENODEV;
6 const struct file_operations *old_fops, *new_fops = NULL;
7
8 mutex_lock(&misc_mtx);
9
10 list_for_each_entry(c, &misc_list, list) {
11 if (c->minor == minor) {
12 new_fops = fops_get(c->fops);
13 break;
14 }
15 }
16
17 if (!new_fops) {
18 mutex_unlock(&misc_mtx);
19 request_module('char-major-%d-%d', MISC_MAJOR, minor);
20 mutex_lock(&misc_mtx);
21
22 list_for_each_entry(c, &misc_list, list) {
23 if (c->minor == minor) {
24 new_fops = fops_get(c->fops);
25 break;
26 }
27 }
28 if (!new_fops)
29 goto fail;
30 }
31
32 err = 0;
33 old_fops = file->f_op;
34 file->f_op = new_fops;
35 if (file->f_op->open) {
36 file->private_data = c;
37 err=file->f_op->open(inode,file);
38 if (err) {
39 fops_put(file->f_op);
40 file->f_op = fops_get(old_fops);
41 }
42 }
43 fops_put(old_fops);
44 fail:
45 mutex_unlock(&misc_mtx);
46 return err;
47 }
1 int misc_register(struct miscdevice * misc)
2 {
3 struct miscdevice *c;
4 dev_t dev;
5 int err = 0;
6
7 INIT_LIST_HEAD(&misc->list);
8
9 mutex_lock(&misc_mtx);
10 list_for_each_entry(c, &misc_list, list) {
11 if (c->minor == misc->minor) {
12 mutex_unlock(&misc_mtx);
13 return -EBUSY;
14 }
15 }
16
17 if (misc->minor == MISC_DYNAMIC_MINOR) {
18 int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
19 if (i >= DYNAMIC_MINORS) {
20 mutex_unlock(&misc_mtx);
21 return -EBUSY;
22 }
23 misc->minor = DYNAMIC_MINORS - i - 1;
24 set_bit(i, misc_minors);
25 }
26
27 dev = MKDEV(MISC_MAJOR, misc->minor);
28
29 misc->this_device = device_create(misc_class, misc->parent, dev,
30 misc, '%s', misc->name);
31 if (IS_ERR(misc->this_device)) {
32 int i = DYNAMIC_MINORS - misc->minor - 1;
33 if (i < DYNAMIC_MINORS && i >= 0)
34 clear_bit(i, misc_minors);
35 err = PTR_ERR(misc->this_device);
36 goto out;
37 }
38
39 /*
40 * Add it to the front, so that later devices can 'override'
41 * earlier defaults
42 */
43 list_add(&misc->list, &misc_list);
44 out:
45 mutex_unlock(&misc_mtx);
46 return err;
47 }
在include/linux/miscdevice.h中定义了miscdevice 结构体,所有的misc模型驱动设备;都在内核围护的一个misc_list链表中;
内核维护一个misc_list链表,misc设备在misc_register注册的时候链接到这个链表,在misc_deregister中解除链接。
1 struct miscdevice {
2 int minor; //次设备号,若为 MISC_DYNAMIC_MINOR 自动分配
3 const char *name; //设备名
4 const struct file_operations *fops; //设备文件操作结构体
5 struct list_head list; //misc_list链表头
6 struct device *parent;
7 struct device *this_device;
8 const char *nodename;
9 mode_t mode;
10 };
misc_register函数
1 int misc_register(struct miscdevice * misc)
2 {
3 struct miscdevice *c;
4 dev_t dev;
5 int err = 0;
6
7 INIT_LIST_HEAD(&misc->list);
8
9 mutex_lock(&misc_mtx);
10 list_for_each_entry(c, &misc_list, list) {
11 if (c->minor == misc->minor) {
12 mutex_unlock(&misc_mtx);
13 return -EBUSY;
14 }
15 }
16
17 if (misc->minor == MISC_DYNAMIC_MINOR) {
18 int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
19 if (i >= DYNAMIC_MINORS) {
20 mutex_unlock(&misc_mtx);
21 return -EBUSY;
22 }
23 misc->minor = DYNAMIC_MINORS - i - 1;
24 set_bit(i, misc_minors);
25 }
26
27 dev = MKDEV(MISC_MAJOR, misc->minor);
28
29 misc->this_device = device_create(misc_class, misc->parent, dev,
30 misc, '%s', misc->name);
31 if (IS_ERR(misc->this_device)) {
上一篇:从samsung提供内核进行移植
下一篇:linux驱动开发之九鼎板载蜂鸣器驱动测试
推荐阅读最新更新时间:2026-03-21 10:53
- LM2904DMR2G 函数发生器运算放大器的典型应用
- DEMO9RS08KA2: DEMO9RS08KA2 Demonstration Board
- MCP73871EV,MCP73871 锂离子电池充电器评估板
- STEVAL-IHM039V1,采用 STM32F415 微控制器的双电机控制演示板
- LTC1606CG 演示板、16 位、250ksps ADC
- RT8086B 3.5A、1.2MHz、同步降压转换器的典型应用
- TS4999EIJT 典型应用 免滤波器立体声 2.8 W D 类音频功率放大器,可选择 3D 音效
- LTM4615,采用 15mm-15mm 封装的完整双路和三路输出负载点模块稳压器
- LTC2415-1IGN 24 位 ADC 的典型应用电路使用电阻器阵列在励磁放大器中提供精确匹配
- 使用 Analog Devices 的 LTC1450LIN 的参考设计



单片机HC32F460驱动LED专用芯片T5020串联应用程序和有关自用函数
Linux技术手册
【2025 DigiKey创意大赛】 学伴智盒 - 代码
现代雷达系统的信号设计
BFR340T






京公网安备 11010802033920号