☰
第二章 DRM 框架概述: 2.7 本章小结
2026/10/30 8:15:37 网站建设 项目流程

1. 本章小结

DRM 把 GPU 实现为设备文件。字符设备的三层角色,即驱动、设备实例与一次打开,在 DRM 中对应drm_driver、drm_device与drm_file:一个驱动管理多个设备,一个设备可被多次打开。open()经设备号找到设备与驱动,此后每次ioctl()都由drm_ioctl()在核心表与驱动私有表之间分派。

三个对象按粒度分工。drm_driver是编译期固定的只读表,记录能力位与驱动级回调;drm_device是每个设备实例一份的运行时状态,决定建立哪些节点,并让同一设备的所有文件共享一个address_space,为 CPU 映射提供偏移空间;drm_file是每次打开一份的客户端上下文,handle、同步对象与驱动私有状态都以它为单位隔离和回收。

访问控制分两层:文件权限决定能否打开节点,节点类型与drm_file上的认证、master 状态决定能调用哪些 ioctl。render 节点是无特权的渲染与计算入口,本书讨论的操作都经它进入内核。驱动接入 DRM,就是为这三个对象提供定义:描述表与操作表、内嵌drm_device的设备结构,以及以drm_dev_register()为可见边界的注册与注销路径。

设备、客户端与入口都已就位,ioctl 操作的缓冲区还是一个黑盒。下一章进入 GEM,讨论缓冲区对象的身份、引用与三类访问视图。

2. 本章依赖的其他子系统

DRM 框架层几乎完全建立在 VFS 与设备驱动模型之上。下表列出本章用到的内核子系统、关键入口及本书落点。

子系统在本章何处用到关键机制 / 入口本书落点
VFS 字符设备主设备号 226 的注册、open 时替换操作表(2.2)register_chrdev()、drm_stub_fops、replace_fops()、file->private_datafs/char_dev.c、fs/open.c
VFS 文件生命周期drm_file何时创建与销毁,flush 与 release 的区别(2.4)struct file引用计数、fops->flush/fops->release、fdinfofs/file_table.c、fs/proc/fd.c
设备驱动模型驱动加载、probe/remove、drm_device的分配与注册(2.2、2.6)pci_driver、devm_drm_dev_alloc()、devres 与drmm_*托管资源drivers/base/、drivers/gpu/drm/drm_managed.c
sysfs 与 udev设备节点的命名、属组与权限,drmGetDevices2()聚合同一设备的节点(2.1、2.5)drm_class、drm_devnode()生成dri/前缀、ueventdrivers/gpu/drm/drm_sysfs.c
伪文件系统与 address_space每设备一个匿名 inode,所有文件共享其i_mapping(2.3)simple_pin_fs()、f_mapping、unmap_mapping_range()附录 B.8
进程与凭据CAP_SYS_ADMIN决定初始认证与DRM_ROOT_ONLY,fd 经dup()/fork()/Unix socket 共享(2.4、2.5)capable()、SCM_RIGHTS附录 B.1
并发与热插拔设备拔出后阻止驱动继续访问硬件(2.6)drm_dev_enter()/drm_dev_exit()基于 SRCU,drm_dev_unplug()中synchronize_srcu()附录 B.5

3. 延伸与拓展问题

下列问题沿本章用到的机制向相邻子系统延伸,每题附一个研究入口,供读者自行追踪。

3.1 VFS 与字符设备

  1. 占位操作表:DRM 以register_chrdev()只为主设备号 226 注册了一张drm_stub_fops,真正的操作表在 open 时才由replace_fops()换入。为什么不直接为每个 minor 注册各自驱动的file_operations?replace_fops()换表时如何处理模块引用计数,换表之后f_op还能不能再变?(入口:fs/char_dev.c的chrdev_open()、include/linux/fs.h的replace_fops())

  2. 一次 close 不等于一次 release:dup()、fork()与SCM_RIGHTS传递的 fd 共享同一个struct file,只有最后一个引用消失时才会调用release,从而销毁drm_file。struct file的引用计数由谁增减?进程退出时内核如何逐个关闭它的 fd?(入口:fs/file_table.c的fput()、fs/file.c;本书附录 B.1)

  3. fdinfo:drm_driver.show_fdinfo输出的显存与引擎统计出现在/proc/<pid>/fdinfo/<fd>中。procfs 如何把这个文件路由到具体驱动?drm-usage-stats规范约定了哪些键,gputop、nvtop一类工具如何据此统计每进程的 GPU 用量?(入口:fs/proc/fd.c、Documentation/gpu/drm-usage-stats.rst)

3.2 设备模型与用户空间设备管理

  1. 托管资源的两种生命期:驱动在 probe 中混用devm_*与drmm_*。前者随struct device解绑释放,后者随drm_device最后一个引用释放。设备已被拔出、而某个进程仍持有打开的 fd 时,哪些资源必须用drmm_*管理才不会被提前释放?(入口:drivers/base/devres.c、drivers/gpu/drm/drm_managed.c)

  2. 节点从哪里来:DRM 核心创建设备时并不设定/dev/dri/renderD128的属组与权限位。设备节点由 devtmpfs 创建还是由 udev 创建?udev 规则如何把 render 节点授予render组,systemd-logind 又如何在会话切换时调整 card 节点的访问权限?(入口:drivers/base/devtmpfs.c、drm_devnode();systemd 的50-udev-default.rules)

3.3 内存映射

  1. 借来的 address_space:drm_device的匿名 inode 从不缓存页,却借用了address_space的偏移坐标与i_mmap映射登记。unmap_mapping_range()如何经i_mmap区间树找到所有映射了某段偏移的 VMA?如果每个节点各用自己的字符设备 inode,会在哪一步失效?(入口:mm/memory.c的unmap_mapping_range();本书附录 B.8、第 3 章 CPU 视图)

3.4 并发、凭据与内核数据结构

  1. 热拔出的读侧保护:drm_dev_enter()用 SRCU 读锁包住硬件访问,drm_dev_unplug()置位后以synchronize_srcu()等待所有读侧退出。这里为什么用 SRCU 而不用普通 RCU?读侧临界区内允许睡眠意味着什么?(入口:drivers/gpu/drm/drm_drv.c、kernel/rcu/srcutree.c;本书附录 B.5)

  2. 认证的边界:drm_file的authenticated初值取自capable(CAP_SYS_ADMIN)。在用户命名空间中,capable()与ns_capable()的判定有何不同,容器内的进程打开 primary 节点时会得到什么结果?render 节点免认证之后,隔离 GPU 访问的责任落到了哪一层?(入口:kernel/capability.c;本书附录 B.1)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询