2. 内核编译环境搭建:获取不同版本内核源码、配置与编译4.x与6.x内核、使用QEMU搭建测试环境
内核驱动移植适配的第一步,是建立一个可重复、可验证的编译与测试环境。本章将指导你从零搭建一套支持Linux 4.x与6.x双版本内核的编译环境,并使用QEMU虚拟机进行快速验证。这套环境将贯穿整个课程,用于后续所有驱动移植实验。
环境概览:推荐使用Ubuntu 22.04 LTS或Debian 12作为宿主机。宿主机内核版本不影响目标内核的编译,但需要安装必要的交叉编译工具链与依赖库。
2.1 获取不同版本内核源码
Linux内核源码托管于kernel.org及各大镜像站。为满足4.x与6.x双版本实验需求,建议通过git克隆官方仓库,并通过标签(tag)切换版本。
2.1.1 方法一:使用Git克隆主线仓库
# 克隆主线仓库(仅首次)
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
cd linux
# 查看所有可用标签
git tag | grep -E '^v4\.|^v6\.' | head -20
# 检出4.19稳定版(LTS)
git checkout v4.19.325
# 检出6.6稳定版(LTS)
git checkout v6.6.63
2.1.2 方法二:直接下载压缩包
若网络带宽有限或仅需特定版本,可直接下载tarball:
# 下载4.19 LTS
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.325.tar.xz
tar -xf linux-4.19.325.tar.xz
# 下载6.6 LTS
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.63.tar.xz
tar -xf linux-6.6.63.tar.xz
| 内核版本 | 类型 | 适用场景 | 长期支持 |
|---|---|---|---|
| v4.19.x | LTS | 旧平台驱动移植基线 | 至2024年12月 |
| v5.10.x | LTS | 过渡版本参考 | 至2026年12月 |
| v6.6.x | LTS | 新平台驱动开发基线 | 至2029年12月 |
版本选择建议:本课程以v4.19.325代表4.x系列,以v6.6.63代表6.x系列。两者均为LTS版本,社区支持良好,驱动API差异典型。
2.2 配置与编译4.x与6.x内核
内核编译分为配置与编译两个阶段。配置阶段决定哪些功能、驱动被编译进内核或作为模块;编译阶段将源码转换为可执行的二进制镜像与模块。
2.2.1 安装编译依赖
sudo apt update
sudo apt install -y build-essential libncurses-dev bison flex \
libssl-dev libelf-dev bc kmod cpio qemu-system-x86
2.2.2 内核配置
推荐使用defconfig生成默认配置,再通过menuconfig进行微调:
# 进入内核源码目录
cd linux-4.19.325
# 生成x86_64默认配置
make defconfig
# 图形化配置界面(可选)
make menuconfig
# 关键配置项检查(4.x)
# - CONFIG_MODULES=y # 模块支持
# - CONFIG_DRIVER_TEST=m # 示例驱动(如有)
# - CONFIG_DEBUG_INFO=y # 调试符号
对于6.x内核,配置流程完全一致,但需注意新配置项的出现:
cd linux-6.6.63
make defconfig
make menuconfig
# 6.x新增关键配置项
# - CONFIG_DRM=y # 直接渲染管理器
# - CONFIG_IOMMU_SUPPORT=y # IOMMU支持
# - CONFIG_FW_LOADER_USER_HELPER=n # 固件加载策略变更
配置陷阱:6.x内核默认启用了
CONFIG_CFI_CLANG(控制流完整性),若使用GCC编译需手动关闭,否则链接阶段会报错。在menuconfig中搜索并设置为n。
2.2.3 编译内核与模块
# 使用多核加速编译(-j参数根据CPU核心数调整)
make -j$(nproc) bzImage
# 编译内核模块
make -j$(nproc) modules
# 安装模块到临时目录(用于QEMU挂载)
make modules_install INSTALL_MOD_PATH=../modules_4.19
编译产物说明:
| 文件/目录 | 路径 | 说明 |
|---|---|---|
bzImage |
arch/x86/boot/bzImage |
压缩后的内核镜像,QEMU直接加载 |
System.map |
源码根目录 | 符号表,调试时用于地址解析 |
.config |
源码根目录 | 本次编译的完整配置 |
modules |
INSTALL_MOD_PATH指定目录 |
可加载内核模块集合 |
2.3 使用QEMU搭建测试环境
QEMU配合virtio设备,可以在宿主机上快速启动编译好的内核,无需物理硬件。本节构建一个最小根文件系统,用于驱动加载与测试。
2.3.1 创建最小根文件系统
使用busybox构建一个约10MB的initramfs:
# 下载并编译busybox
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1
make defconfig
make -j$(nproc)
make install
# 创建initramfs目录结构
mkdir -p initramfs/{bin,sbin,etc,proc,sys,dev,lib/modules}
cp -r _install/* initramfs/
# 创建init脚本
cat > initramfs/init << 'EOF'
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
echo "Hello from QEMU Kernel Test!"
exec /bin/sh
EOF
chmod +x initramfs/init
# 打包为cpio归档
cd initramfs
find . | cpio -o -H newc | gzip > ../initramfs.cpio.gz
2.3.2 启动QEMU虚拟机
# 启动4.19内核
qemu-system-x86_64 \
-kernel linux-4.19.325/arch/x86/boot/bzImage \
-initrd initramfs.cpio.gz \
-append "console=ttyS0" \
-nographic \
-m 512M \
-smp 2 \
-device virtio-net-pci \
-device virtio-blk-pci,drive=testdisk \
-drive file=test.img,if=none,id=testdisk,format=raw
# 启动6.6内核(参数完全一致)
qemu-system-x86_64 \
-kernel linux-6.6.63/arch/x86/boot/bzImage \
-initrd initramfs.cpio.gz \
-append "console=ttyS0" \
-nographic \
-m 512M \
-smp 2 \
-device virtio-net-pci
快速验证:启动后看到
Hello from QEMU Kernel Test!提示符,说明内核启动成功。输入uname -a可确认内核版本。
2.3.3 加载驱动模块测试
将编译好的内核模块复制到initramfs中,启动后手动加载:
# 在宿主机上复制模块到initramfs
cp -r ../modules_4.19/lib/modules/* initramfs/lib/modules/
# 重新打包initramfs
cd initramfs && find . | cpio -o -H newc | gzip > ../initramfs_with_mods.cpio.gz
# QEMU启动后加载模块
insmod /lib/modules/4.19.325/kernel/drivers/test_driver.ko
lsmod | grep test_driver
2.4 环境验证与常见问题
完成上述步骤后,应能分别在4.19与6.6内核下启动QEMU并加载驱动模块。下表列出常见问题及解决方案:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| QEMU启动后黑屏 | 未指定console=ttyS0 |
在-append中添加串口控制台参数 |
模块加载报错Invalid module format |
模块与内核版本不匹配 | 确认uname -r与模块目录版本一致 |
编译时undefined reference |
配置项缺失或工具链版本不兼容 | 检查.config中相关CONFIG_*是否启用 |
| QEMU无法识别virtio设备 | 内核未编译virtio驱动 | 启用CONFIG_VIRTIO_PCI=y与CONFIG_VIRTIO_BLK=y |
环境就绪检查清单:
- ✅ 4.19与6.6内核源码已获取并解压
- ✅ 两个版本均能成功编译
bzImage - ✅ 使用QEMU可分别启动两个内核版本
- ✅ 至少有一个测试驱动模块可正常加载
2.5 本章小结
通过本章操作,你已掌握:
- 从kernel.org获取4.x与6.x内核源码的两种方法
- 使用
defconfig+menuconfig进行内核配置,并识别版本间的配置差异 - 编译生成
bzImage与内核模块,并安装到指定目录 - 使用busybox构建最小initramfs,并通过QEMU启动双版本内核
- 在QEMU虚拟机内加载驱动模块,验证基本功能
这套环境将作为后续所有驱动移植实验的基准平台。建议将4.19与6.6的编译产物分别保存,便于快速切换测试。