开发环境搭建:虚拟机与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
小提示: 我个人习惯把工具链路径加到.bashrc里,这样每次打开终端就不用重新设环境变量了。省心。

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
核心要点: 根文件系统是内核启动后的「家」。没有它,内核会panic。BusyBox就是帮你快速建好这个「家」的工具。

内核编译与启动

终于到了最激动人心的环节——编译内核并启动它。

下载内核源码:

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提示符,说明你的内核跑起来了!

注意: 如果你用的是ARM架构,记得选对machine type(-M参数)。不同的开发板对应不同的machine。我刚开始时总搞混,后来干脆用QEMU自带的virt机型,省事。

知识体系总览

下面这张图,是我整理的本章节知识结构。你可以把它当作路线图:

开发环境搭建知识体系 目标:搭建可运行的内核开发环境 虚拟机与QEMU 硬件模拟环境 交叉编译工具链 跨架构编译 BusyBox 根文件系统制作 内核编译 配置与构建 QEMU安装与配置 • qemu-system-arm • 模拟器参数设置 工具链安装 • gcc-arm-linux • 环境变量配置 BusyBox制作 • 静态编译配置 • 目录与设备创建 内核编译 • defconfig配置 • zImage编译 QEMU启动内核 + 根文件系统 ✅ 内核成功启动!

常见问题与避坑指南

  • 内核启动后卡住不动:多半是根文件系统没挂上。检查initrd路径和格式是否正确。我曾经因为cpio打包时忘了加--format=newc参数,折腾了半小时。
  • 提示「Kernel panic - not syncing」:别慌。通常是找不到根文件系统。确认一下console参数和initrd参数是否匹配。
  • QEMU启动后黑屏:试试加上-nographic参数,用串口输出。有些模拟器默认走图形界面,但我们的环境没有图形驱动。
  • 交叉编译报错:检查CROSS_COMPILE环境变量是否设置正确。注意后面的横线不能少,比如arm-linux-gnueabihf-,少个横线就找不到工具链。
我的经验: 刚开始别追求完美。先用默认配置把内核跑起来,看到启动日志再说。后面再慢慢加功能、调参数。一口吃不成胖子,内核学习也是。

好了,环境搭好了,内核也跑起来了。接下来你就可以放心大胆地读源码、改代码、调试了。记住,这个环境是你的「安全区」,随便折腾,大不了重来一次。


公众号:蓝海资料掘金营,微信deep3321