KMSKernel Mode Setting,内核模式设置)是 Linux DRM 中让内核负责显示模式配置的机制,包括分辨率、刷新率、显示接口、扫描输出、显示平面和页面翻转。

它解决的是“谁有权、在什么时候、用什么硬件状态把哪张图像送到哪个屏幕上”的问题。

核心问题

显示输出不是普通文件写入。屏幕需要稳定的像素时序,显卡或 显示控制器 要按固定节奏从内存中读取图像,再通过 HDMI、DisplayPort、eDP、MIPI DSI 等接口送出去。

如果显示模式由用户态程序随意切换,会带来几个问题:

  • 系统启动、登录界面、桌面会话和崩溃恢复之间很难交接屏幕控制权。
  • 多个程序可能同时想改分辨率、刷新率或显示缓冲。
  • GPU 渲染和扫描输出之间需要同步,否则会撕裂或显示半成品。
  • 热插拔、休眠恢复和多显示器布局需要内核级状态管理。

KMS 把显示硬件状态放在内核的 DRM 驱动里,由拥有显示权限的合成器或显示服务器通过受控接口提交变更。

核心对象

对象含义关注点
connector物理或逻辑显示接口HDMI、DP、eDP、DSI、是否连接、EDID
encoder像素流到接口信号的编码单元哪些 connector 可用、硬件路由限制
CRTC产生扫描时序的显示控制器分辨率、刷新率、vblank、扫描位置
plane可叠加 [[DRM Plane显示平面]]
framebuffer被扫描输出的图像描述指向 帧缓冲、像素格式、stride、尺寸
mode显示模式宽高、刷新率、时钟、同步参数
atomic commit原子提交显示状态一次性验证和应用多对象状态

核心机制

KMS 的现代用法通常是 atomic modesetting:用户态先构造一组“新显示状态”,内核先验证,再在安全时机一次性应用。

典型流程如下:

  1. 枚举资源:用户态读取 connector、CRTC、plane、encoder 和 mode 列表。
  2. 选择显示路径:选择哪个 connector 接到哪个 CRTC,选择主 plane 和目标 framebuffer。
  3. 构造属性集合:设置 connector 的 CRTC、CRTC 的 mode、plane 的源矩形和目标矩形。
  4. test-only 验证:内核检查硬件是否支持这组组合,例如格式、缩放、带宽和路由限制。
  5. atomic commit:验证通过后提交真实变更。
  6. 等待 vblank / page flip:在合适 扫描输出 周期切换 framebuffer,减少撕裂。
  7. 释放旧缓冲:收到 flip 完成事件后,旧 framebuffer 可以被复用或销毁。

可以把页面翻转理解为:

display_state.framebuffer = next_framebuffer
apply_at_next_vblank(display_state)
  • next_framebuffer 是下一帧要显示的图像。
  • vblank 是垂直消隐期,屏幕刚扫完一帧、尚未开始下一帧的时间窗口。
  • apply_at_next_vblank 不是普通赋值,而是让硬件在不撕裂的时机切换扫描源。

工程用途

  • Linux 桌面合成器用 KMS 控制显示器、光标、overlay 和页面翻转。
  • 嵌入式设备用 KMS 调试屏幕 bring-up、MIPI DSI/eDP 面板、背光和显示时序。
  • 游戏或 kiosk 系统可以绕过传统窗口系统,直接使用 DRM/KMS 全屏输出。
  • 显示调试工具 modetest 可以列出 KMS 对象并尝试设置模式。

调试 KMS 时常看 connector 是否 connected、EDID 是否读到、CRTC 是否绑定、plane 是否支持目标格式、framebuffer stride 是否正确,以及 dmesg 中的带宽或模式验证失败信息。

边界与常见坑

  • KMS 不是密钥管理服务:本文的 KMS 是 Kernel Mode Setting;云安全里的 KMS 是 KMS(密钥管理服务)
  • KMS 只负责显示模式和扫描输出:GPU 渲染命令、着色器执行和显存调度属于 DRM 的渲染路径或用户态驱动。
  • 设置成功不等于有画面:背光、电源、面板 init 序列、像素格式和线缆连接都可能导致黑屏。
  • legacy modesetting 和 atomic modesetting 不是同一套模型:现代合成器更依赖 atomic commit,因为它能一次验证整组状态。
  • vblank 同步不正确会出现撕裂或卡顿:页面翻转太早、太晚或没等 fence 都可能造成可见异常。

相关术语