ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

0-README-前言

0-README-前言 本手册以宋宝华《Linux 设备驱动开发详解基于最新的 Linux 4.0 内核》的知识体系为蓝本按照 Linux 7.2.5 源码学习整理而成。1. 本手册的基线内核源码linux-7.2.5内核版本7.2.5教材《Linux 设备驱动开发详解基于最新的 Linux 4.0 内核》推荐Host主机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/LED[02-驱动设计硬件基础]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、kfifo[09-异步通知与异步IO]SIGIO、fasync、AIO、io_uring、异步驱动接口[10-中断与时钟]中断架构、threaded IRQ、工作队列、timer、hrtimer、延时[11-内存与IO访问]内存分配、I/O 端口、ioremap、mmap、DMA、IOMMU[12-驱动软件架构]platform、设备模型、分层、misc、输入/RTC/显示/终端[13-块设备驱动]bio、blk-mq、gendisk、虚拟块设备、MMC[14-网络设备驱动]net_device、NAPI、skb、virtio-net、ethtool、XDP[15-I2C驱动]I²C core、adapter、client、i2c-stub、AT24/regmap[16-USB驱动]USB host、URB、设备驱动、gadget、configfs、Type-C[17-SPI与总线架构类比]SPI controller/device/driver、I²C/SPI/USB 架构对比[18-设备树]DTS/DTC/DTB、compatible、地址、中断、GPIO、clock、OF API[19-电源管理]cpufreq、cpuidle、regulator、OPP、PM QoS、runtime PM[20-芯片级移植与底层驱动]clockevent、irqchip、SMP、earlycon、GPIO、pinctrl、CCF、dmaengine[21-设备驱动调试]GDB/KGDB、printk、ftrace、perf、eBPF、Oops、KASAN、lockdep[22-QEMU实验总览]无开发板实验矩阵、完整启动脚本、故障排查[23-旧内核到7.2.5迁移]4.0 API 到 7.2.5 API 的逐项替换表[24-源码阅读与参与开发]源码地图、调用链阅读、git/lore、checkpatch、提交规范[附录A-原书知识点覆盖矩阵]原书全部目录项到本手册的映射[附录B-API速查与术语表]常用 API、错误码、术语和实验检查表4. 统一 QEMU 实验环境4.1 安装宿主依赖Ubuntu/Debian 可执行sudoaptupdatesudoaptinstall-y\build-essentialgitbcbison flex libssl-dev libelf-dev libncurses-dev\pahole cpiorsynckmod 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 perltarxz-utils如果发行版的 QEMU 没有virtio-spiSPI 章节仍可用软件 SPI 控制器或 GPIO bit-bang 控制器完成实验。QEMU 设备是否可用用以下命令检查qemu-system-x86_64-devicehelp|grep-Evirtio|i2c|spi|gpio|usbqemu-system-aarch64-machinevirt-devicehelp|grep-Evirtio|spi|gpio4.2 配置并编译内核所有构建产物放到源码树之外避免污染源码exportKSRC~/works/study/linux-7.2.5exportKBUILD~/works/study/build/linux-7.2.5-x86_64mkdir-p$KBUILDmake-C$KSRCO$KBUILDx86_64_defconfigmake-C$KSRCO$KBUILDmenuconfigmake-C$KSRCO$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在宿主机建立目录exportROOTFS~/works/study/qemu-rootfsrm-rf$ROOTFSmkdir-p$ROOTFS/{bin,sbin,etc,proc,sys,dev,run,tmp,mnt,lib/modules}cp/usr/bin/busybox$ROOTFS/bin/busyboxforxinshmountumountinsmod rmmod lsmod modprobedmesgcatechosleepmknodmkdirlsddcpmvpsgrepfindchmodchown;doln-sfbusybox$ROOTFS/bin/$xdone写入$ROOTFS/init#!/bin/busybox sh/bin/busybox--install-s/binmount-tproc none /procmount-tsysfs none /sysmount-tdevtmpfs none /devmount-tdebugfs none /sys/kernel/debug2/dev/nullmount-tconfigfs none /sys/kernel/config2/dev/nullecho Linux 7.2.5 QEMU initramfs cat/proc/versionexec/bin/sh赋予执行权限并打包chmodx$ROOTFS/initcd$ROOTFSfind.-print0|cpio--null-ov--formatnewc|gzip-9~/works/study/initramfs.cpio.gzfind . -print0从当前目录你 cd进去的 $ROOTFS递归列出所有文件。-print0用 \0而不是换行来分隔文件名。这样文件名里有空格、引号、换行都不会被拆错。cpio --null -ov --formatnewccpio “copy in, copy out”一个很老的 Unix 归档工具跟 tar是同类东西——把一堆文件打包成单个流或单个文件。它的原始设计就是两条方向cpio -ocopy-out从标准输入读文件路径列表去磁盘抓内容打包输出到 stdout。cpio -icopy-in从 stdin 读归档解包到磁盘。cpio -pcopy-pass不打包直接把文件从一个目录树复制到另一个目录树。-ov就是 copy-out verbose。gzip -9把 cpio 流压缩-9是最高压缩级别。因为 newc头部有冗余、文件内容也没压过压缩率通常很好。4.4 启动 QEMUexportKBUILD~/works/study/build/linux-7.2.5-x86_64exportROOTFS~/works/study/qemu-rootfsexportINITRD~/works/study/initramfs.cpio.gz qemu-system-x86_64\-m2G-smp2\-kernel$KBUILD/arch/x86/boot/bzImage\-initrd$INITRD\-appendconsolettyS0 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$KSRCO$KBUILDINSTALL_MOD_PATH$ROOTFSmodules_install或者给 QEMU 增加 9p 共享目录qemu-system-x86_64...\-virtfslocal,path~works/study/share,mount_taghostshare,security_modelnoneguest 中执行mkdir-p/mnt/hostmount-t9p-otransvirtio,version9p2000.L hostshare /mnt/host5. 学习方法每个章节按“原理 - 7.2.5 源码路径 - 最小实验 - 观察点 - 常见错误”阅读。不要只抄代码先确认设备如何被枚举、驱动如何匹配、资源从哪里来、锁在哪个上下文获取、失败路径如何回滚。遇到 API 不确定时以源码中的函数原型和Documentation/为准而不是以搜索引擎中的旧博客为准。6. 安全边界本手册中的模块面向 QEMU 实验。真实产品驱动还必须考虑越界、整数溢出、用户指针校验和 hardened usercopyDMA 与 IOMMU 边界、地址宽度、cache 一致性probe 失败回滚和热插拔电源管理、时钟、regulator 和 runtime PM并发、内存序、锁顺序和中断上下文限制固件加载、签名、更新、回滚和安全启动许可证兼容性、GPL 符号边界和供应链要求。
返回列表