3. Linux内核显示框架
本章是显示子系统的基石。在 Linux 内核中,显示管理经历了从混乱的 Framebuffer 时代到统一 DRM/KMS 架构的演进。理解这三者的关系,是进行驱动开发和多屏扩展的前提。
核心观点: DRM 是显示子系统的“容器”和“调度器”,KMS 是“模式设置引擎”,而 Framebuffer 是“像素数据缓冲区”。现代驱动开发应基于 DRM/KMS,而非直接操作 Framebuffer。
3.1 DRM (Direct Rendering Manager) 架构
DRM 是 Linux 内核中负责图形显示和渲染管理的框架。它最初为解决多个 X Server 同时访问显卡的冲突而设计,现已演变为所有现代 GPU 和显示控制器的标准驱动模型。
3.1.1 DRM 核心组件
DRM 架构分为用户空间和内核空间两部分,通过 /dev/dri/card0 等设备节点进行交互。
| 层级 | 组件 | 功能描述 |
|---|---|---|
| 用户空间 | libdrm | 用户态库,封装内核 ioctl 调用,提供统一的 API |
| 用户空间 | Mesa/GPU 驱动 | 实现 OpenGL/Vulkan 等图形 API,通过 DRM 提交渲染命令 |
| 内核空间 | DRM Core | 通用框架,管理 GEM、调度、文件操作等 |
| 内核空间 | DRM Driver | 硬件相关代码,实现具体的 GPU/显示控制器操作 |
| 内核空间 | KMS | 内核模式设置,负责显示时序、分辨率、连接器管理 |
关键设备节点:
/dev/dri/card0:主设备,用于 3D 渲染和 KMS 操作。/dev/dri/controlID64:用于显示控制(如多屏布局),无需渲染能力。/dev/dri/renderD128:纯渲染节点,用于无显示输出的计算任务。
3.1.2 DRM 软件架构图
下图展示了 DRM 在 Linux 显示栈中的位置及其内部模块关系:
3.2 KMS (Kernel Mode Setting) 核心概念
KMS 是 DRM 框架中负责显示模式设置的核心子系统。它将显示模式切换(如分辨率、刷新率、显示布局)的控制权从用户空间(X Server)移入内核,实现了原子化、无闪烁的显示配置。
3.2.1 KMS 四大对象
KMS 通过四个核心对象描述和管理显示管线:
| 对象 | 符号 | 职责 | 类比 |
|---|---|---|---|
| CRTC | crtc | 扫描输出控制器,负责从 Framebuffer 读取数据并生成显示时序 | 投影仪的光机 |
| Encoder | encoder | 将 CRTC 输出的像素数据编码为特定接口信号(HDMI、DP、LVDS) | 信号转换器 |
| Connector | connector | 物理连接器,检测显示器是否插入、读取 EDID 信息 | 插座 |
| Plane | plane | 硬件图层,支持叠加多个 Framebuffer 实现合成(如光标、视频层) | 幻灯片叠加层 |
3.2.2 KMS 显示管线流程图
数据从 Framebuffer 到显示器的完整流程:
原子操作 (Atomic Modeset): 现代 KMS 支持原子 API,允许在一次事务中同时设置 CRTC、Encoder、Connector 和 Plane 的状态,避免中间状态导致的屏幕闪烁。
3.3 Framebuffer 与 DRM 的关系
Framebuffer 是显示系统中历史最悠久的概念,但在 DRM 框架下,它的角色发生了根本性变化。
3.3.1 传统 Framebuffer 的局限
- 单缓冲: 早期 fbdev 只支持单个显示缓冲区,无法实现多屏独立控制。
- 无硬件加速: 所有像素操作由 CPU 完成,无法利用 GPU 的 2D/3D 加速能力。
- 模式设置混乱: 分辨率切换依赖
fbset工具,容易导致系统不稳定。 - 多屏支持差: 每个显示设备需要独立的 fbdev 实例,管理复杂。
3.3.2 DRM 中的 Framebuffer 角色
在 DRM 框架中,Framebuffer 不再是“显示设备”,而是“内存对象”。
| 特性 | 传统 fbdev | DRM Framebuffer |
|---|---|---|
| 本质 | 显示设备抽象 | 内存缓冲区抽象 |
| 创建方式 | 内核静态分配 | 用户空间通过 drmModeAddFB() 动态创建 |
| 关联对象 | 直接映射到显存 | 关联到 GEM 对象,可被 GPU 共享 |
| 多屏支持 | 每个屏一个 fbdev | 多个 CRTC 可引用同一个 Framebuffer |
| 生命周期 | 驱动加载时创建 | 用户空间管理,可随时创建/销毁 |
3.3.3 关系总结图
下图展示了 Framebuffer 在 DRM 框架中的位置及其与 KMS 对象的关系:
开发避坑: 不要在新驱动中使用
linux/fb.h 的 fb_ops 接口。DRM 框架提供了 drm_fb_helper 来兼容旧 Framebuffer 应用,但核心驱动逻辑应完全基于 DRM/KMS 的 drm_crtc、drm_encoder、drm_connector 和 drm_plane 结构体。
3.4 本章小结
- DRM 是 Linux 显示驱动的核心框架,提供用户空间与内核空间的标准化接口。
- KMS 是 DRM 的子模块,通过 CRTC、Encoder、Connector、Plane 四个对象管理显示管线。
- Framebuffer 在 DRM 中降级为“像素数据容器”,由用户空间动态管理,不再承担设备抽象职责。
- 多屏扩展的实现依赖于 KMS 对象的灵活组合:一个 CRTC 对应一个显示输出,多个 CRTC 可共享同一个 Framebuffer 或使用独立缓冲区。