---
title: DRM 与图形
url: https://doc.liz6.com/linux-kernel/10-drivers-and-device-model/03-drm-and-graphics
locale: zh
area: linux-kernel
tags:
- linux-kernel
- 驱动与设备模型
date: 2026-06-30
modified: 2026-06-30
description: Linux 有两套图形栈:fbdev(1990s)只是向显存写像素,DRM(2010s+)提供完整的现代 GPU 接口——KMS 管显示模式设置(atomic modesetting 让多显示器配置变成原子操作),GEM 管显存分配和跨进程共享(DMA-BUF 在 GPU 和 Wayland compositor 之…
---

# DRM 与图形

> Linux 有两套图形栈:fbdev(1990s)只是向显存写像素,DRM(2010s+)提供完整的现代 GPU 接口——KMS 管显示模式设置(atomic modesetting 让多显示器配置变成原子操作),GEM 管显存分配和跨进程共享(DMA-BUF 在 GPU 和 Wayland compositor 之间零拷贝传递 buffer)。amdgpu 和 i915 是这两个子系统的最大消费者。
> 内核版本: 2.6 ~ 6.x

## 概述

Linux 上有两套图形栈：fbdev（framebuffer，1990s）和 DRM（Direct Rendering Manager，2010s+）。fbdev 只是向显存写像素——没有 GPU 加速、没有多平面合成、没有 vsync 同步。DRM 提供完整的现代 GPU 接口：模式设置 (KMS)、显存管理 (GEM)、GPU 命令提交 (render) 和跨设备 buffer 共享 (DMA-BUF)。

用户态看到的是 `/dev/dri/card0`（主 GPU）和 `/dev/dri/renderD128`（render-only，不需要 mode setting 权限）。Mesa 和 Vulkan 驱动通过这些设备文件与内核通信。

## DRM 三个核心子系统

### KMS (Kernel Mode Setting): 显示管线

KMS 管理"如何把像素送到显示器"。涉及的硬件抽象：

- **CRTC** (阴极射线管控制器——历史名称保留): 扫描控制器，从 framebuffer 读像素，按 timing 产生 video signal。每个 CRTC 驱动一个显示器
- **Encoder**: 把 CRTC 的像素流编码为物理接口格式（TMDS for HDMI, LVDS for laptop panel, DisplayPort）
- **Connector**: 物理端口（HDMI-A-1, DP-2, eDP-1）。检测显示器热插拔（HPD），读 EDID（显示器能力描述：支持的分辨率、刷新率）
- **Plane**: 叠加层。Primary plane = 主 framebuffer。Overlay plane = 硬件加速的叠加（视频播放、鼠标光标）。现代 GPU 有 multiple planes 可以硬件合成

这些对象构成一条 pipeline: `CRTC → Encoder → Connector`。用户态通过 `DRM_IOCTL_MODE_*` ioctl 配置这条管线。

### Atomic Modesetting

旧 API 是逐步设置参数——先改 CRTC mode，再改 connector，等——每一步中间态可能在屏幕上闪烁。Atomic modesetting 把整个显示状态封装为一个 `drm_atomic_state` 结构：

```c
// 构造一次 atomic commit:
struct drm_atomic_state *state = drm_atomic_state_alloc(dev);
// 添加 CRTC/plane/connector property 修改
drm_atomic_commit(state);
// → 验证 (check) → 如果通过, 在 vblank 期间原子应用 → 无闪烁过渡
```

关键性质：全或无——验证失败（如分辨率不被支持），整个 commit 被拒绝，显示保持不变。这消除了"设备已改了一半"的中间态。

### GEM (Graphics Execution Manager): 显存管理

GPU 内存不是简单的 malloc——它涉及 VRAM（显存）、GTT（Graphics Translation Table，部分可见的系统内存）、不同引擎的可见性约束。GEM 提供 driver-agnostic 的 buffer 管理：

```c
// 分配 GPU buffer (由驱动实现):
struct drm_gem_object *obj = drm_gem_object_create(dev, size);
// → 返回 handle → 用户态 mmap → 访问 buffer 内容
```

关键特性：**DMA-BUF**。GPU buffer 可以导出为一个 file descriptor (`drm_prime_handle_to_fd`)，另一个 GPU 或 V4L2 设备通过该 fd import——实现**零拷贝跨设备共享**。Wayland compositor 就是这样把 client 渲染的 buffer 直接送到显示引擎，不需要 CPU 复制。

## GPU 驱动架构: KMD + UMD 分离

现代 GPU 驱动分为两部分：

**KMD (Kernel Mode Driver)**: `amdgpu.ko`, `i915.ko`, `nouveau.ko`。负责模式设置（显示）、显存管理（GEM/TTM）、命令提交（ring buffer）、fence 同步、固件管理。

**UMD (User Mode Driver)**: Mesa (OpenGL/Vulkan) 或 NVIDIA 的闭源驱动。负责把 OpenGL/Vulkan API 翻译为 GPU 命令，着色器编译。通过 `/dev/dri/renderD*` 通信——不需要 mode setting 权限，也不需要 root。

KMD 提供的是**基础设施**（分配 buffer、提交命令），UMD 提供的是**应用 API**。这种分离意味着 Mesa 可以独立于内核更新，新 OpenGL 版本不需要重编内核。

## fbdev → DRM 迁移

fbdev 是 1990s 的帧缓冲接口：`mmap(fbdev_fd)` 得到显存映射，直接写像素。没有 vsync、没有多 plane、没有 GPU 加速。现代系统通过 `drm_fb_helper` 在 DRM 之上模拟 fbdev 接口——为了兼容老程序（如 fbi, directfb）。但底层仍然是 DRM。

## 参考

- **源码**: `drivers/gpu/drm/` (core), `drivers/gpu/drm/amd/` (amdgpu), `drivers/gpu/drm/i915/`, `include/drm/`, `include/uapi/drm/`
- **内核文档**: `Documentation/gpu/`
- **Mesa**: docs.mesa3d.org

*Keywords: DRM, KMS, GEM, atomic modesetting, CRTC, plane, DMA-BUF, amdgpu, i915, fbdev, Wayland*
