Skip to content

第一百三十八章:设备模型

合道期

涉及内核源码:

林小源在设备山脉的深处,发现了一块巨大的基石。

基石嵌入山体最深处,上面刻满了密密麻麻的字符——。每一道刻痕都散发着微弱的光芒,像是一张巨大的网络,把整个山脉中的所有设备都串联在一起。

"这是什么?"林小源蹲下来,用手指触摸那些刻痕。

基石突然震动了一下。一个低沉的、带着回响的声音从地底传来:

"我是 kobject。设备模型的基石。"

林小源吓得往后跳了一步。只见基石表面的刻痕缓缓亮起,浮现出一个半透明的人影。那人影通体漆黑,表面光滑如镜,没有五官,只有一双眼睛——眼睛里映着一个不断递增的数字:

"那是引用计数。"kobject 说,"我的存在是为了两件事——第一,追踪每个内核对象的引用计数,确保没人用的时候自动释放;第二,在 sysfs 中创建对应的条目,让用户空间能看到内核世界里的设备。"

"你就是所有设备的基类?"

"对。"kobject 说,"device 结构体里嵌入了我。driver 结构体里也嵌入了我。kset 是我的集合体——把相关的 kobject 组织在一起,对应 sysfs 中的一个目录。"

c
/*
 * 设备模型的核心结构:
 *
 * kobject:
 *   内核对象的基类
 *   引用计数、sysfs 表示
 *   嵌入在其他结构中
 *
 * kset:
 *   kobject 的集合
 *   对应 sysfs 中的目录
 *
 * device:
 *   设备的抽象
 *   包含 kobject
 *   关联驱动、总线
 *
 * device_driver:
 *   驱动的抽象
 *   包含操作函数
 *
 * bus_type:
 *   总线类型
 *   管理设备和驱动的匹配
 */

printf("=== 设备模型 — 设备管理的框架 ===\n\n");

printf("设备模型的核心结构:\n\n");

printf("kobject:\n");
printf("  内核对象的基类\n");
printf("  引用计数\n");
printf("  sysfs 表示\n\n");

printf("kset:\n");
printf("  kobject 的集合\n");
printf("  对应 sysfs 目录\n\n");

printf("device:\n");
printf("  设备的抽象\n");
printf("  包含 kobject\n");
printf("  关联驱动、总线\n\n");

printf("--- 层次结构 ---\n");
printf("  bus_type\n");
printf("  ├── device 1\n");
printf("  │   └── kobject\n");
printf("  ├── device 2\n");
printf("  │   └── kobject\n");
printf("  └── device_driver\n\n");

printf("--- sysfs 对应 ---\n");
printf("/sys/\n");
printf("├── bus/\n");
printf("│   ├── pci/\n");
printf("│   └── usb/\n");
printf("├── devices/\n");
printf("│   └── pci0000:00/\n");
printf("└── class/\n");
printf("    └── net/\n\n");

printf("--- 设备注册 ---\n");
printf("device_register(&dev):\n");
printf("  注册设备\n");
printf("  创建 sysfs 条目\n");
printf("  尝试匹配驱动\n\n");

printf("--- 驱动注册 ---\n");
printf("driver_register(&drv):\n");
printf("  注册驱动\n");
printf("  尝试匹配设备\n");

"sysfs?"林小源想起了之前在用户空间见过的 /sys/ 目录。

kobject 的眼睛闪了闪:"你在用户空间看到的 /sys/,就是我的投影。每一个 kobject 在 sysfs 中都有一个目录——目录里有属性文件,显示设备的状态、配置、驱动信息。"

他伸手一挥,空中浮现出一棵树:

/sys/
├── bus/
│   ├── pci/
│   └── usb/
├── devices/
│   └── pci0000:00/
└── class/
    └── net/

"这棵树就是设备模型在用户空间的映射。"kobject 说,"/sys/bus/ 下是总线类型,/sys/devices/ 下是设备层次结构,/sys/class/ 下是设备类别。你通过读写这些文件,就能查询甚至控制设备。"

林小源盯着那棵树,忽然明白了:设备模型不仅仅是内核内部的数据结构——它还是内核和用户空间之间的桥梁。内核通过 sysfs 把设备信息暴露给用户空间,用户空间通过 sysfs 了解和管理设备。

"设备模型的核心是总线-设备-驱动的关系。"kobject 说。

他的身体裂开,露出内部的结构——一根根细线从他的核心向外延伸,连接着三种不同颜色的光团:蓝色的是总线,绿色的是设备,红色的是驱动。

"总线负责匹配。"kobject 说,"当一个新设备注册时——比如你插了一块网卡——总线会遍历所有已注册的驱动,用 函数检查每个驱动是否跟这个设备匹配。如果匹配上了,就调用驱动的 函数。"

"反过来呢?"

"反过来也一样。当一个新驱动注册时——比如你加载了一个内核模块——总线会遍历所有已注册的设备,找到匹配的设备,调用 probe。"

林小源看着那三种光团之间的连线,心中浮现出一个画面:设备注册时找驱动,驱动注册时找设备,总线在中间做媒人。这就是 Linux 设备模型的核心——一个自动匹配的框架。

"所以同一套驱动代码,"林小源说,"不管是先插设备还是先加载驱动,都能正常工作?"

kobject 点了点头:"这就是设备模型的优雅之处。"


道藏笔记

内核启示

设备模型是内核管理设备的框架。

核心结构:

  • kobject — 内核对象基类
  • kset — kobject 集合
  • device — 设备抽象
  • device_driver — 驱动抽象
  • bus_type — 总线类型

总线-设备-驱动关系:

  • 总线管理匹配
  • 设备注册时匹配驱动
  • 驱动注册时匹配设备

设备模型是"组织"的框架——让设备管理有序。


破关试炼

设备模型之试

设备模型完成 device 与 driver 匹配后,负责绑定并初始化设备的驱动回调是什么?

答对后才能继续滑动和进入下一章。

以修仙之名,悟内核之道