Skip to content

🔨 整理中 · 这一篇讲 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 miscdevicemisc_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)极简:

c
struct miscdevice {
    int minor;            /* 次设备号;传 MISC_DYNAMIC_MINOR 让内核自动分配 */
    const char *name;     /* /dev 下的节点名 */
    const struct file_operations *fops;   /* 文件操作表(同 chardev) */
    struct device *parent;
    ...
};

注册就两步:

c
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_MINORMISC_RTC_MINORMISC_HWPOISON_INJECT_MINOR)——给历史遗留的固定次设备号(/dev/rtc 等)。新设备直接用 MISC_DYNAMIC_MINOR 自动分配即可,不用碰这些。

动手试试

  1. 读本站 01 chardev 的 demo 代码——它用的就是 misc,对照本篇理解每个字段
  2. 写个最简 misc 设备:misc_register + 一个只实现 .open/.read 的 fops,cat /dev/mydev 验证
  3. ls -l /dev/mydev 看主设备号 10、次设备号自动分配(对比手编 cdev 的自定义主设备号)
  4. 思考题: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

基于 VitePress 构建