1. DRM 框架概述
Direct Rendering Manager (DRM) 是 Linux 内核中负责图形显示与渲染的核心子系统。它向上为用户态图形栈(如 Mesa、Wayland、Xorg)提供标准接口,向下抽象 GPU、Display Controller、Encoder、Connector 等硬件资源。理解 DRM 在 Linux 图形栈中的位置及其与 FBDEV、V4L2 的区别,是掌握整个显示子系统的第一步。
1.1 DRM 在 Linux 图形栈中的位置
Linux 图形栈从应用层到内核层通常分为四层:应用/合成器、用户态图形库、内核显示驱动、硬件。DRM 位于内核层,是连接用户态与硬件的桥梁。
1.2 DRM 与 FBDEV / V4L2 的区别
Linux 内核中存在多个与显示/图像相关的子系统,初学者容易混淆。下表从核心定位、功能范围、应用场景三个维度进行对比。
| 对比维度 | DRM (Direct Rendering Manager) | FBDEV (Frame Buffer Device) | V4L2 (Video for Linux 2) |
|---|---|---|---|
| 核心定位 | 现代 GPU 显示与渲染管理 | 简单帧缓冲输出 | 视频采集与输出 |
| 显示模式设置 | 支持 (KMS 核心功能) | 有限 (通过 FBIO 扩展) | 不支持 |
| GPU 加速 | 原生支持 (GEM/Dumb Buffer) | 不支持 | 不支持 |
| 多平面合成 | 支持 (Overlay/Cursor 平面) | 不支持 | 不支持 |
| 视频采集 | 不支持 | 不支持 | 核心功能 |
| 典型设备节点 | /dev/dri/card0, /dev/dri/renderD128 | /dev/fb0 | /dev/video0 |
| 现代桌面环境 | Wayland/Xorg 标准后端 | 仅用于早期或嵌入式系统 | 摄像头、电视卡 |
1.3 DRM 核心组件介绍
DRM 子系统由三个核心组件构成:DRM Core(基础框架)、KMS(显示模式设置)、GEM(图形内存管理)。三者协同工作,为上层提供完整的显示服务。
1.3.1 DRM Core — 基础框架
DRM Core 是 DRM 子系统的骨架,负责设备注册、文件操作接口、IOCTL 分发、驱动模型抽象。它定义了 struct drm_driver、struct drm_device、struct drm_file 等核心数据结构,并管理用户态与内核态的交互通道。
// DRM Core 核心数据结构关系(简化)
struct drm_driver {
const struct file_operations *fops;
int (*load)(struct drm_device *, unsigned long flags);
void (*unload)(struct drm_device *);
// ... 驱动回调函数
};
struct drm_device {
struct drm_driver *driver;
struct drm_minor *primary; // /dev/dri/card0
struct drm_minor *render; // /dev/dri/renderD128
struct drm_mode_config mode_config; // KMS 配置
// ... 设备状态
};
1.3.2 KMS (Kernel Mode Setting) — 显示模式设置
KMS 是 DRM 中负责显示输出管理的组件。它抽象了显示管线中的硬件单元:CRTC(显示控制器)、Encoder(编码器)、Connector(连接器)、Plane(平面)。KMS 提供原子模式设置(Atomic Modeset)接口,允许用户态在一次原子提交中同时更新多个显示参数,避免撕裂和闪烁。
1.3.3 GEM (Graphics Execution Manager) — 图形内存管理
GEM 是 DRM 中负责 GPU 内存分配与管理的组件。它提供统一的 API 来分配、映射、共享 GPU 缓冲区。GEM 的核心概念包括:
- GEM Object:内核中表示一块 GPU 内存的基本单位,每个对象有唯一的 handle。
- Handle:用户态通过 handle 引用 GEM Object,handle 是 per-file 的。
- Flink (GEM Global Name):将 GEM Object 导出为全局名称,用于跨进程共享。
- DMA-BUF:现代 DRM 中推荐的缓冲区共享机制,支持跨设备(GPU ↔ VPU ↔ Display)共享。
- Dumb Buffer:用于非 GPU 加速场景的简单帧缓冲,CPU 可直接访问。
// GEM 核心操作示例(用户态通过 libdrm 调用)
// 分配 GEM Object
uint32_t handle;
struct drm_mode_create_dumb create = {
.width = 1920,
.height = 1080,
.bpp = 32,
};
ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
handle = create.handle;
// 映射 GEM Object 到用户态地址空间
struct drm_mode_map_dumb map = {
.handle = handle,
};
ioctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
void *addr = mmap(NULL, create.size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, map.offset);
// 将 GEM Object 提交为帧缓冲
uint32_t fb_id;
drmModeAddFB(fd, 1920, 1080, 24, 32, create.pitch, handle, &fb_id);
1.4 本章小结
DRM 是 Linux 内核显示子系统的核心,它通过 DRM Core、KMS、GEM 三个组件分别管理设备框架、显示输出和 GPU 内存。与 FBDEV 相比,DRM 支持 GPU 加速、多平面合成和原子模式设置;与 V4L2 相比,DRM 专注于显示输出而非视频采集。掌握 DRM 在图形栈中的位置及其核心组件,为后续深入学习 KMS 原子接口、GEM 缓冲区共享、驱动开发等内容打下坚实基础。