2. 实现DRM驱动加载与卸载
任务目标
编写一个最小DRM驱动内核模块,在模块加载时完成DRM设备对象的分配与注册,在卸载时执行逆序释放,并通过内核日志验证加载/卸载流程正确执行。
环境依赖
- Linux内核源码树(含DRM子系统头文件),版本 ≥ 4.19
- 内核头文件包(
linux-headers-$(uname -r)) - Make工具与C编译器
关键完整代码
创建文件 drm_load_unload.c:
#include <linux/module.h>
#include <linux/pci.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
#include <drm/drm_print.h>
static struct drm_device *dev;
static int drm_load_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
int ret;
dev = drm_dev_alloc(NULL, &pdev->dev);
if (IS_ERR(dev))
return PTR_ERR(dev);
ret = drm_dev_register(dev, 0);
if (ret) {
drm_dev_put(dev);
dev = NULL;
return ret;
}
pci_set_drvdata(pdev, dev);
drm_info(dev, "DRM device registered successfully\n");
return 0;
}
static void drm_load_remove(struct pci_dev *pdev)
{
struct drm_device *drm_dev = pci_get_drvdata(pdev);
if (!drm_dev)
return;
drm_dev_unregister(drm_dev);
drm_dev_put(drm_dev);
pci_set_drvdata(pdev, NULL);
dev = NULL;
pr_info("DRM device unregistered and released\n");
}
static const struct pci_device_id drm_load_pci_ids[] = {
{ PCI_DEVICE(0x1234, 0x5678) },
{ }
};
static struct pci_driver drm_load_driver = {
.name = "drm_load_unload",
.id_table = drm_load_pci_ids,
.probe = drm_load_probe,
.remove = drm_load_remove,
};
module_pci_driver(drm_load_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("DRM Course");
MODULE_DESCRIPTION("Minimal DRM load/unload example");
创建 Makefile:
obj-m := drm_load_unload.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
编译与加载
make
sudo insmod drm_load_unload.ko
sudo rmmod drm_load_unload
验证方法
加载后执行 dmesg | tail -5,应看到:
[timestamp] drm_load_unload 0000:00:00.0: DRM device registered successfully
卸载后再次执行 dmesg | tail -5,应看到:
[timestamp] DRM device unregistered and released
同时确认 ls /sys/bus/pci/drivers/drm_load_unload/ 在加载期间存在,卸载后消失。
说明
- 代码使用虚拟PCI设备ID
0x1234:0x5678,实际硬件需替换为真实设备ID;若仅验证模块生命周期,可改用module_init/module_exit直接调用drm_dev_alloc/register,但当前实现更贴近真实DRM驱动的PCI探测流程。 - 资源释放顺序必须为:先
drm_dev_unregister注销设备,再drm_dev_put释放引用,不可颠倒。 - 若系统无匹配PCI设备,probe不会触发,此时可添加
new_id或使用虚拟化设备(如QEMU的virtio-gpu)验证。