探索QEMU虚拟设备与Linux内核驱动的完美结合
本章将带领您学习如何在QEMU虚拟环境中创建自定义硬件设备,并为其编写专业的Linux内核驱动程序。通过这个项目,您将掌握虚拟设备开发的完整流程。
使用QEMU的-device
参数可以在虚拟机中动态添加虚拟硬件设备:
qemu-system-x86_64 \
-kernel bzImage \
-append "console=ttyS0 root=/dev/sda" \
-device edu,id=my_edu_device \
-drive file=rootfs.ext4,format=raw \
-nographic
步骤 | 描述 | 关键函数/宏 |
---|---|---|
1. 设备探测 | 识别QEMU创建的虚拟设备 | pci_register_driver() |
2. 初始化 | 设置设备资源和数据结构 | pci_enable_device() |
3. 操作实现 | 实现设备的具体功能 | file_operations |
4. 中断处理 | 处理设备产生的中断 | request_irq() |
5. 清理释放 | 安全地释放资源 | pci_release_regions() |
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#define DEVICE_NAME "qemu_edu"
#define CLASS_NAME "qedu"
static int major_num;
static struct class* edu_class = NULL;
static struct device* edu_device = NULL;
static int edu_open(struct inode *inodep, struct file *filep) {
printk(KERN_INFO "QEMU EDU device opened\n");
return 0;
}
static ssize_t edu_read(struct file *filep, char *buffer, size_t len, loff_t *offset) {
printk(KERN_INFO "QEMU EDU device read operation\n");
return 0;
}
static struct file_operations fops = {
.open = edu_open,
.read = edu_read,
};
static int __init edu_init(void) {
printk(KERN_INFO "QEMU EDU driver initialized\n");
major_num = register_chrdev(0, DEVICE_NAME, &fops);
if (major_num < 0) {
printk(KERN_ALERT "Failed to register device\n");
return major_num;
}
edu_class = class_create(THIS_MODULE, CLASS_NAME);
if (IS_ERR(edu_class)) {
unregister_chrdev(major_num, DEVICE_NAME);
return PTR_ERR(edu_class);
}
edu_device = device_create(edu_class, NULL, MKDEV(major_num, 0), NULL, DEVICE_NAME);
if (IS_ERR(edu_device)) {
class_destroy(edu_class);
unregister_chrdev(major_num, DEVICE_NAME);
return PTR_ERR(edu_device);
}
return 0;
}
static void __exit edu_exit(void) {
device_destroy(edu_class, MKDEV(major_num, 0));
class_unregister(edu_class);
class_destroy(edu_class);
unregister_chrdev(major_num, DEVICE_NAME);
printk(KERN_INFO "QEMU EDU driver unloaded\n");
}
module_init(edu_init);
module_exit(edu_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("嵌入式系统课");
MODULE_DESCRIPTION("QEMU EDU Device Driver");
obj-m += qemu_edu.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
make
insmod qemu_edu.ko
ls -l /dev/qemu_edu
dmesg | tail
cat /dev/qemu_edu
rmmod qemu_edu
调试提示:使用printk()
输出调试信息,通过dmesg
查看输出结果。确保QEMU命令行正确设置了设备参数。