前言
本系列文章为Linux kernel学习过程中的笔记,仅作学习交流用途。
This series of articles are notes during the learning process of Linux kernel, only for learning and communication.
本篇为Direct Rendering Manager (DRM)入门。
一、什么是DRM?
DRM全称为Direct Rendering Manager,是Linux kernel中负责管理现代显卡的GPU接口的子系统,可以提供多种API,允许用户空间程序与GPU交互,包括发送指令、数据到GPU和执行操作等。用户空间程序可以使用DRM API来操控GPU执行硬件加速3D渲染,视频解码和通用GPU计算等操作。
二、DRM概述
在此之前,Linux kernel已经有一套API称为fbdev,用于管理framebuffer,但是这套方案不适用于现代GPU硬件。特别是当2个及以上程序想要同时控制同一块硬件并按照各自的方式设置硬件资源时,大多数情况下程序都会崩溃。
于是就引入DRM这套子系统,可以使得多个程序来协同地使用硬件资源。DRM拥有对GPU的独家管理权,负责初始化和管理硬件资源,包括command queue,memory等,想要使用GPU的程序就发送请求给DRM。DRM就像一个管理者/对接人一样,负责处理这些请求并避免潜在的冲突。
逐渐地,DRM开始把一些本属于用户空间程序的功能收揽到自己麾下,比如framebuffer管理,模式设置,内存共享对象,内存同步等功能。这些扩展出来的功能又被赋予了特定名词,比如 Graphics Execution Manager (GEM) 和 kernel mode-setting (KMS)。
三、DRM软件架构
DRM驻留在内核空间中,所以用户空间程序必须使用内核系统调用来请求服务。但是DRM没有定义专属的系统调用,而是遵循了Unix的"everything is a file"的原则,通过文件系统命名空间来暴露GPU。
DRM使用/dev
下面的设备文件来暴露GPU,每个由DRM检测到的GPU被定义为一个DRM device,并且设备文件/dev/dri/cardX
(X为0,1,2…)被创建用来与之交互。 用户空间进程想要与GPU交互,就必须打开这个文件,并且使用 ioctl 调用来与DRM通信,不同的的ioctl对应于不同的DRM API。
小结:GPU被DRM检测到,创建设备文件/dev/dri/cardX,用户空间程序通过ioctl调用对应的DRM API,实现对应功能
为了促进用户空间进程和DRM子系统之间的交互,libdrm被创建出来,这个library实际上是一个包装器,为每个DRM API的ioctl提供C语言形式的函数,还包括常量,结构体和其他有用元素。libdrm主要有2个作用:1.避免直接暴露内核接口给用户层;2.用户程序之间可以重用和共享代码。
小结:libdrm位于用户空间,以C语言的形式包装DRM API对应的ioctl,可以避免直接暴露内核接口,并且用户程序间可以重用、共享libdrm
下面,将DRM进一步的细分:
对每一种支持的硬件,DRM包括2部分:通用的DRM core和针对特定硬件的DRM driver
DRM core提供基本框架,供不同的DRM driver注册,并提供给用户空间一组最小的具备通用、独立于硬件的ioctl
DRM driver实现API的硬件相关部分, 特定于其支持的GPU。DRM driver应当包含未被DRM core涵盖的剩余ioctl,同时它也可以扩展API,提供只在特定硬件上有效的额外ioctl。当DRM driver 提供了额外增加的API,与之对应地,用户空间的libdrm也要扩展libdrm-driver,这样才能与额外增加的ioctl交互。
小结:DRM core提供不与特定硬件相关的、通用的ioctl,强调common
DRM driver提供与硬件强相关、特定GPU的ioctl,它补全DRM core的ioctl,还可以扩展特定硬件对应的ioctl,强调specific