1. 本手册的基线内核源码~/study/linux-7.2.5内核版本7.2.5推荐宿主Ubuntu/Debian x86_64QEMU 建议 8.0 或更新版本。主要实验架构x86_64嵌入式总线实验使用aarch64 virt或软件总线模型。学习前提C 语言、Linux 命令行、进程/虚拟内存/文件描述符基本概念。2. 为什么不能直接照搬 Linux 4.0 代码Linux 4.0 到 7.2.5 之间驱动开发发生了以下关键变化ARM32 板级文件基本退出历史舞台设备树和 ACPI 成为硬件描述主路径。字符设备仍以cdev和file_operations为核心但class_create()等接口签名已经改变。中断处理以request_threaded_irq()、devm_*()和 IRQ domain 为主tasklet 只适合维护遗留代码。定时器必须使用timer_setup()旧的init_timer()已删除。网络驱动使用netdev_ops、NAPI、DMA 映射和ethtool_ops旧式init_etherdev路径不再适用。块设备统一到 blk-mq旧请求队列接口已经删除现代驱动通常实现submit_bio或queue_rq。I²C/SPI/USB 的核心仍然是“核心层 控制器驱动 设备驱动”但设备实例化改为设备树、ACPI、软件节点或 configfs。电源管理、时钟、pinctrl、regulator、OPP、genpd 和 runtime PM 成为平台驱动的基础设施。调试工具从单纯的printk/GDB 扩展到 dynamic debug、ftrace、perf、eBPF、KASAN、KCSAN、lockdep、pstore 和 QEMU gdbstub。构建系统支持 Clang/LLVM、外部模块、模块签名、Rust、可复现构建和 SBOM驱动代码必须显式处理现代编译器的警告。3. 手册结构文件内容01-驱动概述与开发环境驱动作用、分类、QEMU 环境、Hello World/LED02-驱动设计硬件基础CPU、存储器、总线、时序、原理图、仪器03-Linux内核与内核编程内核演进、组成、构建、Kconfig/Kbuild、编码风格04-Linux内核模块模块结构、参数、符号、引用计数、外部模块编译05-文件系统与设备文件VFS、设备文件、devtmpfs、udev、sysfs、设备模型06-字符设备驱动cdev、设备号、file_operations、globalmem 完整实验07-并发控制原子操作、自旋锁、mutex、RCU、完成量、锁验证08-阻塞与非阻塞IO等待队列、O_NONBLOCK、poll/select/epoll、kfifo09-异步通知与异步IOSIGIO、fasync、AIO、io_uring、异步驱动接口10-中断与时钟中断架构、threaded IRQ、工作队列、timer、hrtimer、延时11-内存与IO访问内存分配、I/O 端口、ioremap、mmap、DMA、IOMMU12-驱动软件架构platform、设备模型、分层、misc、输入/RTC/显示/终端13-块设备驱动bio、blk-mq、gendisk、虚拟块设备、MMC14-网络设备驱动net_device、NAPI、skb、virtio-net、ethtool、XDP15-I2C驱动I²C core、adapter、client、i2c-stub、AT24/regmap16-USB驱动USB host、URB、设备驱动、gadget、configfs、Type-C17-SPI与总线架构类比SPI controller/device/driver、I²C/SPI/USB 架构对比18-设备树DTS/DTC/DTB、compatible、地址、中断、GPIO、clock、OF API19-电源管理cpufreq、cpuidle、regulator、OPP、PM QoS、runtime PM20-芯片级移植与底层驱动clockevent、irqchip、SMP、earlycon、GPIO、pinctrl、CCF、dmaengine21-设备驱动调试GDB/KGDB、printk、ftrace、perf、eBPF、Oops、KASAN、lockdep22-QEMU实验总览无开发板实验矩阵、完整启动脚本、故障排查23-旧内核到7.2.5迁移4.0 API 到 7.2.5 API 的逐项替换表附录A-原书知识点覆盖矩阵原书全部目录项到本手册的映射附录B-API速查与术语表常用 API、错误码、术语和实验检查表4. 统一 QEMU 实验环境4.1 安装宿主依赖Ubuntu/Debian 可执行sudo apt update sudo apt install -y \ build-essential git bc bison flex libssl-dev libelf-dev libncurses-dev \ pahole cpio rsync kmod udev \ qemu-system-x86 qemu-system-arm qemu-utils \ gdb gdb-multiarch device-tree-compiler \ busybox-static e2fsprogs dosfstools \ i2c-tools spi-tools gpiod libgpiod-dev \ python3 perl tar xz-utils如果发行版的 QEMU 没有virtio-spiSPI 章节仍可用软件 SPI 控制器或 GPIO bit-bang 控制器完成实验。QEMU 设备是否可用用以下命令检查qemu-system-x86_64 -device help | grep -E virtio|i2c|spi|gpio|usb qemu-system-aarch64 -machine virt -device help | grep -E virtio|spi|gpio4.2 配置并编译内核所有构建产物放到源码树之外避免污染源码export KSRC~/study/linux-7.2.5 export KBUILD~/study/build/linux-7.2.5_out mkdir -p $KBUILD make -C $KSRC O$KBUILD x86_64_defconfig make -C $KSRC O$KBUILD menuconfig make -C $KSRC O$KBUILD -j$(nproc)menuconfig中至少确认以下选项CONFIG_MODULESy CONFIG_MODULE_UNLOADy CONFIG_DEVTMPFSy CONFIG_DEVTMPFS_MOUNTy CONFIG_TMPFSy CONFIG_PROC_FSy CONFIG_SYSFSy CONFIG_DEBUG_FSy CONFIG_CONFIGFS_FSy CONFIG_9P_FSy CONFIG_NET_9Py CONFIG_NET_9P_VIRTIOy CONFIG_VIRTIO_PCIy CONFIG_VIRTIO_BLKy CONFIG_VIRTIO_NETy CONFIG_VIRTIO_CONSOLEy CONFIG_VIRTIO_INPUTy CONFIG_SERIAL_8250y CONFIG_SERIAL_8250_CONSOLEy CONFIG_PRINTKy CONFIG_KALLSYMSy CONFIG_KALLSYMS_ALLy CONFIG_DEBUG_INFOy CONFIG_GDB_SCRIPTSy CONFIG_DYNAMIC_DEBUGy CONFIG_FTRACEy CONFIG_KPROBESy CONFIG_BPF_SYSCALLy CONFIG_GPIO_SIMm CONFIG_I2C_STUBm CONFIG_SPI_LOOPBACK_TESTm CONFIG_DMA_API_DEBUGy CONFIG_DEBUG_KMEMLEAKy CONFIG_KASANy CONFIG_UBSANy CONFIG_PROVE_LOCKINGy CONFIG_DEBUG_ATOMIC_SLEEPy CONFIG_DEBUG_SPINLOCKy CONFIG_DEBUG_MUTEXESy不建议在第一次实验时同时打开所有调试选项因为 KASAN、lockdep、KCSAN 会显著降低 QEMU 速度并放大内存占用。先建立可启动基线再按章节逐步打开。4.3 制作最小 initramfs在宿主机建立目录export ROOTFS~/study/qemu-rootfs rm -rf $ROOTFS mkdir -p $ROOTFS/{bin,sbin,etc,proc,sys,dev,run,tmp,mnt,lib/modules} cp /usr/bin/busybox $ROOTFS/bin/busybox for x in sh mount umount insmod rmmod lsmod modprobe dmesg cat echo sleep mknod mkdir ls dd cp mv ps grep find chmod chown; do ln -sf busybox $ROOTFS/bin/$x done为什么使用 BusyBoxBusyBox 是一个多调用二进制程序。一个 BusyBox 文件内部实现了大量 Unix/Linux 命令例如sh、ls、cat、mount、insmod、ps、grep等。它根据启动时程序名也就是argv[0]决定自己应该执行哪个命令。比如执行 /bin/ls BusyBox 看到 argv[0] 是 ls 于是运行内部的 ls 实现因为/bin/ls - busybox所以实际执行的是同一个 BusyBox 文件。这样做的优点是体积小不用把几十个独立的/bin/ls、/bin/cat、/bin/cp等程序复制进去。部署简单只需要一个 BusyBox 二进制和一组符号链接。适合最小系统常见于嵌入式系统、initramfs、救援系统、QEMU 测试镜像等场景。功能足够基础虽然每个命令的选项不如 GNU 版本完整但通常足够启动、挂载、调试和加载模块。写入$ROOTFS/init#!/bin/busybox sh # 让 BusyBox 把当前这个 BusyBox 二进制中支持的所有 applet小工具 # 以符号链接的形式安装到 /bin 目录。就是上面写的那个for循环ln -sf busybox $ROOTFS/bin/$x /bin/busybox --install -s /bin mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs none /dev mount -t debugfs none /sys/kernel/debug 2/dev/null mount -t configfs none /sys/kernel/config 2/dev/null echo Linux 7.2.5 QEMU initramfs cat /proc/version exec /bin/sh赋予执行权限并打包chmod x $ROOTFS/init cd $ROOTFS find . -print0 | cpio --null -ov --formatnewc | gzip -9 ~/study/initramfs.cpio.gz4.4 启动 QEMUexport KBUILD~/study/build/linux-7.2.5-x86_64 export ROOTFS~/study/qemu-rootfs export INITRD~/study/initramfs.cpio.gz qemu-system-x86_64 \ -m 2G -smp 2 \ -kernel $KBUILD/arch/x86/boot/bzImage \ -initrd $INITRD \ -append consolettyS0 nokaslr panic1 oopspanic loglevel7 \ -nographic -no-reboot如果宿主支持 KVM可加入-enable-kvm -cpu host。调试时加入-s -S启动 gdbstub再在另一个终端执行gdb $KBUILD/vmlinux (gdb) target remote :1234 (gdb) hbreak start_kernel (gdb) continue4.5 在宿主机和 guest 之间传模块最简单的方法是把模块安装进 initramfsmake -C $KSRC O$KBUILD INSTALL_MOD_PATH$ROOTFS modules_install或者给 QEMU 增加 9p 共享目录qemu-system-x86_64 ... \ -virtfs local,path/home/user/study/shared,mount_taghostshare,security_modelnoneguest 中执行mkdir -p /mnt/host mount -t 9p -o transvirtio,version9p2000.L hostshare /mnt/host5. 学习方法每个章节按“原理 - 7.2.5 源码路径 - 最小实验 - 观察点 - 常见错误”阅读。不要只抄代码先确认设备如何被枚举、驱动如何匹配、资源从哪里来、锁在哪个上下文获取、失败路径如何回滚。遇到 API 不确定时以当前源码中的函数原型和Documentation/为准而不是以搜索引擎中的旧博客为准。6. 安全边界本手册中的模块面向 QEMU 实验。真实产品驱动还必须考虑越界、整数溢出、用户指针校验和 hardened usercopyDMA 与 IOMMU 边界、地址宽度、cache 一致性probe 失败回滚和热插拔电源管理、时钟、regulator 和 runtime PM并发、内存序、锁顺序和中断上下文限制固件加载、签名、更新、回滚和安全启动许可证兼容性、GPL 符号边界和供应链要求。