目录
第一部分:KMD开发基础
GPU驱动架构概述
Windows/Linux下KMD的启动流程与生命周期
Windows KMD启动流程
Linux KMD启动流程
跨平台差异对比
生命周期关键阶段
第一部分:KMD开发基础
GPU驱动架构概述
GPU驱动架构分为用户态(UMD)和内核态(KMD)两层,通过分层设计实现硬件抽象与资源管理的解耦。以Windows的WDDM和Linux的DRM/KMS框架为例:
用户态图形驱动层(UMD)
功能:实现图形API(如DirectX、OpenGL)的调用接口,管理应用层的渲染命令生成、资源分配(如纹理、缓冲区)及同步逻辑。
特点:运行在用户空间,崩溃仅影响单个应用,便于调试和快速迭代。
内核态驱动层(KMD)
功能:直接与硬件交互,管理GPU内存、中断、电源状态及多进程资源调度,提供原子操作和安全机制。
特点:运行在内核空间,错误可能导致系统崩溃(如蓝屏),需严格遵循内核编程规范。
架构协作流程:
应用层→UMD→KMD→硬件:
应用程序通过图形API提交渲染命令,UMD转换为中间指令(如命令缓冲区)。
UMD通过系统调用(如
ioctl)向KMD提交任务,KMD分配GPU资源并调度执行。KMD处理中断并通知UMD任务完成,UMD更新应用状态。
Windows/Linux下KMD的启动流程与生命周期
Windows KMD启动流程
驱动加载
系统启动时:通过
DriverEntry函数注册设备对象,创建符号链接(如\Device\GPU0)。DDK编译:使用Windows Driver Kit(WDK)编译生成
.sys文件,通过.inf文件配置安装参数。注册表初始化:在
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下创建驱动服务项,配置启动类型(如SERVICE_DEMAND_START)。
设备初始化
Probe函数:调用
AddDevice创建设备对象,初始化硬件寄存器、内存映射(MMIO)及中断向量表。资源分配:通过
ExAllocatePoolWithTag分配内核内存池,注册中断处理程序(ISR)。
运行时处理
IRP处理:响应用户态请求(如
IRP_MJ_CREATE/IRP_MJ_CLOSE),管理GPU上下文切换。中断服务:通过
DpcForIsr处理GPU中断,更新任务状态并触发事件通知。
生命周期结束
卸载流程:调用
DriverUnload释放设备对象、注销中断、清理内存池。安全退出:确保所有挂起的IRP完成后再卸载驱动,避免资源泄漏。
关键代码片段(Windows KMD初始化):
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { // 注册设备对象 UNICODE_STRING deviceName, symLinkName; RtlInitUnicodeString(&deviceName, L"\\Device\\GPU0"); RtlInitUnicodeString(&symLinkName, L"\\??\\GPU0"); IoCreateDevice(DriverObject, 0, &deviceName, FILE_DEVICE_GPU, 0, FALSE, &g_DeviceObject); IoCreateSymbolicLink(&symLinkName, &deviceName); // 注册中断处理程序 KeInitializeInterrupt(&g_InterruptObject, GpuIsr, NULL, NULL, 0, LevelSensitive, FALSE); return STATUS_SUCCESS; }Linux KMD启动流程
内核模块加载
编译与安装:通过Makefile编译为
.ko模块,使用insmod或modprobe加载。设备树绑定:在设备树(Device Tree)中定义GPU节点(如
compatible = "armchina,zhouyi"),匹配硬件地址和寄存器映射。
Probe函数初始化
硬件探测:调用
probe函数检测GPU存在性,分配资源(如显存、中断)。DRM注册:通过
drm_dev_register将设备注册到DRM框架,创建/dev/dri/cardX节点。
运行时管理
命令调度:处理用户态提交的渲染命令(如通过
ioctl调用DRM_IOCTL_EXECBUFFER)。内存管理:使用GEM(Graphics Execution Manager)分配显存,实现页表映射与同步。
生命周期结束
卸载流程:调用
remove函数释放显存、注销中断,调用drm_dev_unregister注销设备。资源回收:通过
kfree释放内核对象,确保无残留引用。
关键代码片段(Linux KMD初始化):
static int gpu_probe(struct platform_device *pdev) { // 分配设备结构体 struct gpu_device *gpu = devm_kzalloc(&pdev->dev, sizeof(*gpu), GFP_KERNEL); // 映射寄存器 gpu->regs = devm_ioremap_resource(&pdev->dev, res); // 注册中断 devm_request_irq(&pdev->dev, irq, gpu_isr, 0, "gpu", gpu); // 注册DRM设备 return drm_dev_register(&gpu->ddev, 0); } static void gpu_remove(struct platform_device *pdev) { struct gpu_device *gpu = platform_get_drvdata(pdev); drm_dev_unregister(&gpu->ddev); devm_iounmap(&pdev->dev, gpu->regs); }跨平台差异对比
维度 | Windows KMD | Linux KMD |
|---|---|---|
核心框架 | WDDM(Windows Display Driver Model) | DRM/KMS(Direct Rendering Manager) |
中断处理 | 基于DPC(Deferred Procedure Call) | 基于中断上下文+底半部(Bottom Half) |
内存管理 | VidMm框架管理显存,支持虚拟地址映射 | GEM/TTM管理显存,依赖页表直接操作 |
调试工具 | WinDbg、GPU-Z | Perfetto、Kernel GDB |
生命周期关键阶段
初始化阶段
硬件检测:通过ACPI或设备树获取GPU地址、中断号等参数。
资源分配:申请显存池、中断向量、内核对象(如事件对象)。
运行时阶段
任务调度:接收UMD提交的渲染命令,通过环形缓冲区(Ring Buffer)提交到硬件。
同步控制:使用Fence对象协调CPU/GPU操作顺序,避免资源竞争。
终止阶段
状态清理:重置GPU寄存器、释放预留资源(如显存页表)。
日志记录:输出驱动退出状态,辅助故障排查。
下一节预告:深入解析显存管理,涵盖WDDM的VidMm框架与Linux的GEM机制对比,以及显存压缩与迁移技术。