开发环境搭建:虚拟机与QEMU环境配置、交叉编译工具链安装、BusyBox根文件系统制作、内核编译与启动
说实话,很多初学者一上来就啃内核源码,结果卡在环境搭建上。我见过不少朋友,代码看了三章,结果连编译都过不去。嗯,这其实挺打击人的。
我个人习惯是,先把环境搞利索了,再开始读代码。你想想看,如果连内核都跑不起来,光看代码就像纸上谈兵。今天我就带你一步步把开发环境搭好,保证你能亲手把内核跑起来。
为什么需要虚拟机与QEMU?
直接在你的物理机上编译和运行内核?别闹。万一搞崩了系统,哭都来不及。我刚开始学内核时,就干过这种蠢事——直接在开发机上编译了一个新内核,结果重启后起不来了,折腾了一整天。
所以,我们用虚拟机。QEMU是个好东西,它不仅能模拟完整的硬件环境,还支持调试。说白了,它就是你的「内核沙盒」。你在里面随便折腾,外面稳如泰山。
QEMU环境配置
安装QEMU其实很简单。以Ubuntu为例:
sudo apt-get update
sudo apt-get install qemu-system-arm qemu-system-x86 qemu-utils
我个人建议装完整版,省得后面缺组件。装完后验证一下:
qemu-system-x86_64 --version
看到版本号就说明装好了。嗯,这里要注意,不同发行版的包名可能略有差异,但大差不差。
交叉编译工具链安装
为什么要交叉编译?因为你的开发机是x86架构,但目标机可能是ARM、RISC-V或者其他架构。交叉编译就是在你的电脑上编译出能在其他架构上运行的代码。
我曾经在做一个嵌入式项目时,目标板是ARM Cortex-A系列。当时我直接在板子上编译内核,结果等了两个小时还没编译完。后来换成交叉编译,十分钟搞定。你想想看,这效率差距有多大。
安装ARM交叉编译工具链:
sudo apt-get install gcc-arm-linux-gnueabihf
sudo apt-get install g++-arm-linux-gnueabihf
验证安装:
arm-linux-gnueabihf-gcc --version
如果你要玩RISC-V,那就装这个:
sudo apt-get install gcc-riscv64-linux-gnu
BusyBox根文件系统制作
内核启动后,需要挂载根文件系统。BusyBox就是用来制作最小根文件系统的利器。它把几百个常用命令打包成一个可执行文件,体积小、功能全。
下载BusyBox源码:
wget https://busybox.net/downloads/busybox-1.36.0.tar.bz2
tar -xjf busybox-1.36.0.tar.bz2
cd busybox-1.36.0
配置BusyBox:
make menuconfig
在菜单里,记得选上「Build BusyBox as a static binary (no shared libs)」。为什么要静态编译?因为这样生成的二进制文件不依赖动态库,放到任何系统上都能跑。我在项目中吃过动态库版本不兼容的亏,从那以后,根文件系统里的BusyBox一律静态编译。
编译:
make -j$(nproc)
make install
编译完成后,会在_install目录下生成根文件系统的骨架。接下来我们手动创建一些必要的目录和设备文件:
cd _install
mkdir -p proc sys dev etc/init.d
touch etc/inittab
touch etc/init.d/rcS
chmod +x etc/init.d/rcS
编辑etc/inittab:
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
编辑etc/init.d/rcS:
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
最后,打包成镜像文件:
find . | cpio -o --format=newc > ../rootfs.cpio
gzip -c ../rootfs.cpio > ../rootfs.cpio.gz
内核编译与启动
终于到了最激动人心的环节——编译内核并启动它。
下载内核源码:
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.6.tar.xz
tar -xf linux-6.6.tar.xz
cd linux-6.6
配置内核:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
这里用defconfig生成默认配置。如果你想定制,可以用menuconfig:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
编译内核:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) zImage
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) dtbs
编译完成后,zImage和dtbs文件就在arch/arm/boot/目录下。
启动内核:
qemu-system-arm \
-M virt \
-kernel arch/arm/boot/zImage \
-dtb arch/arm/boot/dts/arm/vexpress-v2p-ca9.dtb \
-initrd ../rootfs.cpio.gz \
-nographic \
-append "console=ttyAMA0"
看到内核启动日志了吗?最后出现一个shell提示符,说明你的内核跑起来了!
知识体系总览
下面这张图,是我整理的本章节知识结构。你可以把它当作路线图:
常见问题与避坑指南
- 内核启动后卡住不动:多半是根文件系统没挂上。检查initrd路径和格式是否正确。我曾经因为cpio打包时忘了加--format=newc参数,折腾了半小时。
- 提示「Kernel panic - not syncing」:别慌。通常是找不到根文件系统。确认一下console参数和initrd参数是否匹配。
- QEMU启动后黑屏:试试加上-nographic参数,用串口输出。有些模拟器默认走图形界面,但我们的环境没有图形驱动。
- 交叉编译报错:检查CROSS_COMPILE环境变量是否设置正确。注意后面的横线不能少,比如arm-linux-gnueabihf-,少个横线就找不到工具链。
好了,环境搭好了,内核也跑起来了。接下来你就可以放心大胆地读源码、改代码、调试了。记住,这个环境是你的「安全区」,随便折腾,大不了重来一次。
公众号:蓝海资料掘金营,微信deep3321