1. DRM 子系统概述:DRM 架构、GEM 与 KMS 核心组件、显示驱动栈全景图

DRM(Direct Rendering Manager)是 Linux 内核中负责图形显示与渲染管理的核心子系统。它向上为用户空间提供统一的显示与渲染接口,向下抽象了 GPU、Display Controller、Encoder、Connector 等硬件差异。理解 DRM 的架构分层、GEM/KMS 两大核心组件以及完整的显示驱动栈,是进行 drm_info 解析与性能调优的基础。

关键认知: DRM 并非一个单一的驱动,而是一个框架。它通过 drm_device 管理显示状态,通过 GEM 管理显存,通过 KMS 管理显示模式与合成。调试时,drm_info 输出的所有信息都源自这三个核心模块的数据结构。

1.1 DRM 架构分层

DRM 子系统在内核中分为三层:

  • DRM Core(核心层): 提供设备注册、文件操作、ioctl 分发、缓冲区管理(GEM)和模式设置(KMS)的通用框架。所有 DRM 驱动都基于此层。
  • DRM Helper(辅助层): 提供通用实现,如 drm_fb_helper(帧缓冲模拟)、drm_atomic_helper(原子提交辅助函数)、drm_bridge(桥接芯片驱动框架)。
  • Driver Layer(驱动层): 具体硬件厂商的实现,如 i915(Intel)、amdgpu(AMD)、msm(Qualcomm)、panfrost(Arm Mali)等。驱动层填充 drm_driver 结构体中的回调函数。
DRM 架构分层图 DRM 架构分层 用户空间 (libdrm / Mesa / Weston / Xorg) 系统调用 / ioctl 接口 DRM Core (核心层) 设备注册 | ioctl 分发 | GEM 框架 | KMS 框架 | 原子提交 DRM Helper (辅助层) drm_fb_helper | drm_atomic_helper | drm_bridge Driver Layer (驱动层) i915 | amdgpu | msm | panfrost | vc4 | ...

1.2 GEM 核心组件

GEM(Graphics Execution Manager)是 DRM 的显存管理框架,负责分配、映射、共享 GPU 缓冲区。drm_info 中关于 buffer objects、handles、size 的信息均来自 GEM 层。

GEM 概念 内核数据结构 说明
GEM Object struct drm_gem_object 代表一个显存缓冲区,包含 size、handle count、dma_buf 等字段。
GEM Handle u32 (用户空间句柄) 用户空间通过 handle 引用 GEM Object,每个进程有独立的 handle 空间。
GEM VMA struct drm_vma_offset_node 管理 GEM Object 在进程地址空间中的映射。
DMA-BUF struct dma_buf 用于跨设备、跨驱动共享 GEM 缓冲区,如 GPU 与 Display Controller 共享。
GEM Prime 扩展接口 提供 drm_gem_prime_export / drm_gem_prime_import 实现 DMA-BUF 导出导入。
调试提示: 使用 drm_info 查看 GEM Objects 列表时,关注 size 和 handle count。如果某个 BO 的 handle count 异常高,可能存在用户空间未关闭 handle 导致的内存泄漏。
GEM 对象关系图 GEM 核心对象关系 用户空间进程 handle (u32) GEM Object size / flags / refcount GPU 显存 物理页 / VRAM handle 查找 dma_buf 映射 DMA-BUF 实现跨驱动共享(GPU ↔ Display)

1.3 KMS 核心组件

KMS(Kernel Mode Setting)是 DRM 中负责显示模式设置、合成和输出的框架。drm_info 中关于 CRTC、Encoder、Connector、Plane 的信息全部来自 KMS 组件。

KMS 组件 内核结构体 功能描述
CRTC struct drm_crtc 代表显示控制器,负责扫描输出、生成时序信号。一个 CRTC 对应一个显示管道。
Encoder struct drm_encoder 将 CRTC 输出的像素数据编码为特定接口信号(如 HDMI、DP、LVDS)。
Connector struct drm_connector 代表物理显示接口(HDMI 端口、DP 端口、eDP 面板),检测显示器热插拔与 EDID。
Plane struct drm_plane 代表硬件图层(Overlay/Primary/Cursor),支持独立缩放、色彩转换和合成。
Bridge struct drm_bridge 代表外部桥接芯片(如 HDMI 转 DP、MIPI 桥接),用于扩展显示输出路径。
常见误区: CRTC 不是指显示器刷新率,而是指显示控制器的扫描输出管道。一个 CRTC 可以连接多个 Encoder,但同一时刻只能激活一条显示链路。drm_info 中 crtc 的 mode 字段显示的是当前激活的显示时序。
KMS 组件连接拓扑图 KMS 显示管道拓扑 Plane (图层) Plane (图层) Plane (光标) CRTC 显示控制器 Encoder 编码器 Connector 接口 显示器 多个 Plane 合成后由 CRTC 扫描输出

1.4 显示驱动栈全景图

从用户空间应用程序到最终显示像素,完整的显示驱动栈涉及多个层次。理解每一层的职责和交互接口,有助于在调试时快速定位问题发生在哪个环节。

  1. 应用程序层: 使用 Wayland/Weston、Xorg、Android HWC 或直接调用 libdrm 的 ioctl。
  2. 用户空间库: libdrm 封装内核 ioctl,Mesa 提供 OpenGL/Vulkan 渲染,Wayland 合成器管理显示合成。
  3. 系统调用层: 通过 drm_ioctl 进入内核,分发到 DRM Core 的处理函数。
  4. DRM Core: 解析 ioctl 命令,调用 GEM 或 KMS 框架的通用实现。
  5. DRM Helper: 提供原子提交、帧缓冲模拟、桥接管理等辅助功能。
  6. 驱动层: 硬件厂商驱动实现具体的寄存器操作、中断处理、DMA 传输。
  7. 硬件层: GPU 渲染、Display Controller 扫描、Encoder 编码、Connector 输出到显示器。
显示驱动栈全景图 Linux 显示驱动栈全景图 应用程序 (Weston / Xorg / Android HWC / 游戏) 用户空间库 (libdrm / Mesa / Wayland) 系统调用层 (ioctl) 内核 DRM 子系统 DRM Core + DRM Helper (GEM / KMS / Atomic) 硬件驱动层 (i915 / amdgpu / msm / ...) 硬件层 (GPU / Display Controller / Encoder / Connector) 像素数据 → 显示器

1.5 原子提交与性能计数器

现代 DRM 驱动使用 Atomic Mode Setting(原子模式设置)来管理显示状态更新。原子提交允许在一个事务中同时更新多个 KMS 对象(CRTC、Plane、Connector),避免中间状态导致的闪烁或撕裂。

性能计数器(Performance Counters)是 drm_info 调试的重要输出,通常包括:

  • vblank 计数: 垂直消隐中断次数,用于衡量显示刷新周期。
  • page flip 计数: 缓冲区交换次数,反映合成器或游戏的帧率。
  • atomic commit 计数: 原子提交成功/失败次数,用于诊断显示配置变更问题。
  • GPU 引擎占用: 渲染引擎、拷贝引擎、视频编解码引擎的利用率。
调试实战: 使用 drm_info 的 -p 或 --properties 参数可以查看每个 KMS 对象的属性值,包括 CRTC_ACTIVE、mode、FB_ID 等。结合 perf 工具统计 vblank 中断频率,可以快速判断显示输出是否稳定。
原子提交流程 原子提交 (Atomic Commit) 流程 1. 获取状态 drm_atomic_get_state 2. 设置属性 set CRTC/Plane props 3. 检查 atomic_check 4. 提交 atomic_commit 整个事务要么全部成功,要么全部回滚,避免中间状态

1.6 本章小结