背景
在 /dev/
目录下的设备节点文件,每套驱动都需要申请一个主设备号Major
,不管是动态申请的或是静态定义的,都需要消耗一个主设备号, 如果一个驱动不需要管理很多的从设备,就会显得有些浪费主设备号。
针对此问题,linux内核提供了一个杂项设备驱动的功能框架。杂项设备也属于字符设备,主要特点是共用同一个主设备号,且固定是10
。 实际应用中,通常只有少数一两个从设备的杂项驱动可以使用该框架,如果驱动支持管理的设备较多,就不要用这个了,还是单独申请一个主设备号为宜。
大致实现
杂项设备子系统的实现也不复杂,主要有:
- 使用固定主设备号
10
来注册主设备号 - 调用
class_create
创建杂项设备类,在/sys/class/misc/
可以查看 - 对于用户注册的杂项驱动,自动调用
device_create
创建设备节点 - 杂项设备仅次设备号不同,misc设备组织成一个链表,内核根据次设备号找到对应设备,然后调用其fops
杂项设备,主要就是对字符设备驱动进行了简单的二次封装,稍微简化了字符设备驱动的编写,同时节约了主设备号。主要是软件框架方面的,硬件相关 的地方肯定还是需要用户驱动自行编写。
使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <linux/miscdevice.h> //for misc device
const struct file_operations my_xxx_fops={
.owner = THIS_MODULE,
.read = my_xxx_read,
.write = my_xxx_write,
.open = my_xxx_open,
.release = my_xxx_release,
.unlocked_ioctl = my_xxx_ioctl,
};
struct miscdevice misc_demodev = {
.minor = MISC_DYNAMIC_MINOR,
.name = "miscdev_xxx", //某设备
.fops = &my_xxx_fops,
.mode = 0666,
};
int __init misc_dev_init(void)
{
//全局设备管理结构体初始化等。
// p_one_inst = kzalloc(sizeof(my_xxx_device_t),GFP_KERNEL);
//设备管理结构体就直接定义并使用全局的。
misc_register(&misc_demodev);
}
void __exit misc_dev_exit(void)
{
misc_deregister(&misc_demodev);
kfree(p_one_inst);
}
不确定能否通过设备文件获取到设备管理结构体,常见示例都是基于全局变量编写的,比较简单。但是也无法管理多个设备,属于缺陷。
查看系统的misc设备
1
2
$ cat /proc/misc
$ ls /sys/class/misc/