🔨 整理中 · 这一篇讲 misc 杂项设备——字符设备的简化封装,01 chardev 那套
cdev/alloc_chrdev_region的轻量替代,适合"一个小字符设备、不想折腾设备号"的场景。素材来自 6.19 源码。本站 chardev 教程用的misc_register就是它。
做什么
01 chardev 讲的字符设备注册要几步:alloc_chrdev_region 申请设备号、cdev_init/cdev_add、手动 device_create 建 /dev 节点。如果只是想"暴露一个小字符设备",这套有点啰嗦。misc 子系统(drivers/char/misc.c)给你个简化封装:填一个 struct miscdevice、misc_register 一下,设备号(共享主设备号 10 + 自动分次号)、/dev 节点、sysfs 全自动。本站 01 chardev 实战就是用的 misc(看 layer-2.yaml 的 chardev session:"misc 设备 /dev/llkd_miscdrv 注册")。这一篇拆 misc 的接口 + 它和 cdev 的关系。
要了解什么
一、struct miscdevice + misc_register
struct miscdevice(include/linux/miscdevice.h:85)极简:
struct miscdevice {
int minor; /* 次设备号;传 MISC_DYNAMIC_MINOR 让内核自动分配 */
const char *name; /* /dev 下的节点名 */
const struct file_operations *fops; /* 文件操作表(同 chardev) */
struct device *parent;
...
};注册就两步:
static struct miscdevice my_dev = {
.minor = MISC_DYNAMIC_MINOR, /* 自动分次号(>255 池,见 chardev 实战) */
.name = "mydev",
.fops = &my_fops,
};
misc_register(&my_dev); /* miscdevice.h:97 — 注册,自动建 /dev/mydev */
/* 用完 */
misc_deregister(&my_dev); /* :98 — 注销 */misc_register 内部做的事:在 misc 共享主设备号(10)下分一个次号、cdev_add 注册 cdev、device_create 建 /dev/<name> 节点 + sysfs 链接。所以 misc 本质就是 chardev 的一层"省事包装"——fops 还是 VFS 那套 file_operations(VFS 讲过),只是设备号/节点管理替你包了。
二、misc vs 原生 cdev:什么时候用哪个
- misc:一个或几个小字符设备、不想管设备号、不需要复杂字符设备特性 → 用 misc,代码短一半。多数"内核暴露个简单接口给用户态"(本站 chardev/ioctl/poll/mmap 教程的 demo)都用 misc。
- 原生 cdev(alloc_chrdev_region + cdev_add):需要自定义主设备号、大量次设备号、或要精细控制 cdev 生命周期 → 用原生。
经验:默认用 misc,不够用了再回原生 cdev。
三、预定义的 minor
include/linux/miscdevice.h 顶部有一堆 #define MISC_XXX_MINOR(如 MISC_DYNAMIC_MINOR、MISC_RTC_MINOR、MISC_HWPOISON_INJECT_MINOR)——给历史遗留的固定次设备号(/dev/rtc 等)。新设备直接用 MISC_DYNAMIC_MINOR 自动分配即可,不用碰这些。
动手试试
- 读本站 01 chardev 的 demo 代码——它用的就是 misc,对照本篇理解每个字段
- 写个最简 misc 设备:
misc_register+ 一个只实现.open/.read的 fops,cat /dev/mydev验证 ls -l /dev/mydev看主设备号 10、次设备号自动分配(对比手编 cdev 的自定义主设备号)- 思考题:misc 用共享主设备号 10,会不会"次设备号耗尽"?对比原生 cdev 自定义主设备号。(提示:minor 是 int,空间大;且 misc 适合小批量)
延伸阅读
- 源码(本仓库
third_party/linux/,6.19.9):include/linux/miscdevice.h:85 struct miscdevice、:97 misc_register/:98 misc_deregister、顶部的MISC_*_MINOR预定义;实现在drivers/char/misc.c(看 misc_register 怎么内部走 cdev_add + device_create)。 - 关联本站:01 chardev 实战用 misc、02 ioctl/03 poll/04 mmap 都基于 misc 设备;
fops的 VFS 分派见 VFS。