试玩 Linux Kernel
基于 Busybox 和 QEMU,我们可以搭建一个非常小的玩具 Linux 系统,可以借此来体验开发编译 Linux 内核的乐趣。
准备工作
由于最近对 Incus System Container 很感兴趣,于是就使用 Incus 创建一个 Debian 12 的容器来进行本次体验。
incus launch mirrors:debian/12 debian12 incus exec debian12 -- bash
进入容器后,安装一些在编译过程中会用的的工具与库。
apt install wget gcc gdb bzip2 bc xz-utils flex bison apt install libncurses-dev libssl-dev libelf-dev apt install cpio qemu-system-x86
接着,创建工作目录 kernel-dev
并下载 Kernel 和 Busybox 的源码:
mkdir kernel-dev cd kernel-dev wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.7.3.tar.xz wget https://www.busybox.net/downloads/busybox-1.36.1.tar.bz2 tar xf linux-6.7.3.tar.xz tar xf busybox-1.36.1.tar.bz2
编译 Kernel
在 Kernel 源码目录下,直接 make defconfig
生成默认配置文件 .config
,编辑其内容,修改 CONFIG_LOCALVERSION
来自定义内核版本标识。最后,make -j $(nproc)
使用所有 CPU 核心来编译内核镜像。
cd linux-6.7.3 make defconfig # Edit .config, eg: CONFIG_LOCALVERSION="-Silver" make -j $(nproc)
编译 Busybox
在 Busybox 源码目录下,通过 make menuconfig
将 Settings -> Build static binary (no shared libs) 选项启用,然后 make -j $(nproc)
编译。
cd busybox-1.36.1 make menuconfig make -j $(nproc)
构建 Initramfs
创建 run 目录来作为我们测试 kernel 的工作目录,在该目录下,继续创建 initramfs
目录,并将编译好的 Kernel 和 Busybox 复制进来,创建 init 脚本作为系统的母进程(PID 为 1)。
mkdir -p run/initramfs/bin cp linux-6.7.3/arch/x86_64/boot/bzImage run/ cp busybox-1.36.1/busybox run/initramfs/bin
init 脚本内容如下,主要负责在内核加载完成后,挂载 /proc
目录,打印一行 “Hello World”,然后返回一个 shell 提供交互。
#!/bin/busybox sh /bin/busybox mkdir -p /proc && /bin/busybox mount -t proc none /proc /bin/busybox echo -e "\nHello World!\n" /bin/busybox sh
另外,需要 chmod +x ./init
使 init 脚本具有可执行权限。
接下来,创建一个 Makefile 脚本,来生成 initramfs 镜像和后续启动 QEMU 虚拟机。
.PHONY: initramfs initramfs: cd ./initramfs && find . -print0 | cpio -ov --null --format=newc | gzip -9 > ../initramfs.img run: qemu-system-x86_64 \ -kernel bzImage \ -initrd initramfs.img \ -m 1G \ -nographic \ -append "earlyprintk=serial,ttyS0 console=ttyS0"
然后 make initramfs
来构建 initramfs.img
磁盘镜像。
此时,run 目录的文件结构如下:
📂run ├──📃Makefile ├──📃bzImage ├──📂initramfs │ ├──📂bin │ │ └── 📃busybox │ └──📃init └──📃initramfs.img
运行系统
终于!此时,只需 make run
就可启动 QEMU 虚拟机,屏幕上会滚动显示一些内核输出,并输出 “Hello World”,然后弹出 shell 等待输入。
可以执行下面的命令,来查看我们之前在 .config
中配置的自定义内核版本标识。
busybox uname -r
最后,通过下面的命令来关闭系统,退出虚拟机。
busybox poweroff -f
结束!