注意:这篇文章上次更新于603天前,文章内容可能已经过时。
This article was last updated603 days ago, the content may be outdated.
本文记录如何在 Ubuntu 24.04 系统上编译和运行 Linux kernel.
主机配置如下:
1 | ./+o+- wgxls@server |
下载 Linux Kernel 源码
下载 Linux Kernel 源码可以分为两种方式,一种是下载源码包,另一种是使用 Git 下载源码。
- 下载源码包
打开 Linux Kernel 官方网址: https://www.kernel.org/
点击黄色按钮,下载最新版本的源码包。

- 使用 Git 下载源码
使用 Git 下载源码会包括所有的历史版本,所以下载的内容比较大,时间也比较长。
可以从 Linux 的 GitHub 镜像仓库下载代码,地址为: https://github.com/torvalds/linux
1 | git clone https://github.com/torvalds/linux.git |
也可以从 Linux 的官方仓库下载代码,地址为: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
从以下三个链接 clone 其中一个就可以了。

1 | git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git |
编译 Linux Kernel
安装编译工具和依赖
以下是一个包含了足够冗余的编译工具和依赖的列表,可以根据自己的需求进行调整。
当然,我也不能保证这些依赖对于你的操作系统是有用的,具体问题需要具体问AI分析。
1 | sudo apt update |
配置内核
编译内核需要用到一下常用的命令:
1 | make mrproper # 清理内核源码 |
make mrproper是 Linux 内核源码树中的一个命令,用于清理内核源码树。它的作用是删除所有生成的文件和配置文件,使源码树恢复到一个干净的状态。具体来说,make mrproper会执行以下操作:
- 删除所有编译生成的文件,包括目标文件(.o 文件)、依赖文件(.d 文件)和可执行文件。
- 删除所有配置文件,包括 .config 文件和生成的头文件(如 include/config 目录下的文件)。
- 删除一些其他生成的文件和目录,如 arch/*/boot 目录下的文件。
make clean用于清理编译过程中生成的文件。它的作用是删除所有生成的文件,但不会删除配置文件。具体来说,make clean会执行以下操作:
- 删除所有编译生成的文件,包括目标文件(.o 文件)、依赖文件(.d 文件)和可执行文件。
make menuconfig是 Linux 内核的配置工具,用于配置内核的编译选项。它提供了一个基于文本的菜单界面,可以让用户方便地选择内核的编译选项。具体来说,make menuconfig会打开一个菜单界面,用户可以在这个界面上选择内核的编译选项,然后保存配置文件。
Linux 的内核配置在 Kconfig 文件中,这些文件位于内核源码树的各个目录中。make menuconfig 会读取这些文件,然后生成一个菜单界面,用户可以在这个界面上选择内核的编译选项。用户选择完毕后,make menuconfig 会将用户的选择保存到 .config 文件中。
make xconfig 和 make gconfig 所作的事情和 make menuconfig 是一样的,只是它们提供了不同的界面。make xconfig 使用 Qt 库,make gconfig 使用 GTK 库。
在本文中,我们使用 make menuconfig 来配置内核。
make -j$(nproc)是编译内核的命令。-j选项用于指定并行编译的任务数,$(nproc)是一个 shell 命令,用于获取系统的 CPU 核心数。这样,make -j$(nproc)就会使用系统的所有 CPU 核心来编译内核。
接下来重点介绍一下 make menuconfig 的使用。
make menuconfig 需要终端有足够的 Size, 最小可以接受的尺寸是 19 行 80 列,否则会出现如下错误:
1 | wgxls@server:~/Desktop/kernel/linux$ make menuconfig |
调整好终端的大小后,重新运行 make menuconfig 即可进入配置界面。
操作规则写在了界面的上方,翻译成中文如下:
Enter: 进入子菜单
高亮的字母是快捷键
Y 是选中,N 是不选中,M 是模块化编译 (也可以使用空格键进行切换)
按两次 Esc 键退出
上下左右移动光标
/ 搜索

这里面由 [ ] 指示的选项只有 选中 和 非选中 两种状态,< > 指示的选项有 选中、非选中、模块化编译 三种状态。
首次编译我们先不作任何修改,直接退出即可。
退出时被询问是否保存配置,选择 Yes 即可。

此时,内核的配置文件 .config 就被保存了。
编译内核
直接执行 make -j$(nproc) 即可开始编译内核。
此过程需要一些时间,根据电脑的性能不同,时间也会有所差异,几分钟到几小时不等。
编译成功的内核镜像位于 arch/x86/boot/bzImage
我们可以看一下编译生成的文件大小:
1 | wgxls@server:~/Desktop/kernel/linux$ ls -lh arch/x86/boot/bzImage |
以及查bzImage的版本信息:
1 | wgxls@server:~/Desktop/kernel/linux$ file arch/x86/boot/bzImage |
这个 bzImage 和 Ubuntu /boot 目录下的 vmlinuz 是一样的,只是名字不一样。
1 | wgxls@server:~/Desktop/kernel/linux$ sudo file /boot/vmlinuz-6.8.0-49-generic |
稍后,我们会用 QEMU 来启动这个 bzImage。
踩坑一:
在编译过程中,可能会出现如下错误:
1 | make[3]: *** 没有规则可制作目标“debian/canonical-certs.pem”,由“certs/x509_certificate_list” 需求。 停止。 |
可以通过清空 SYSTEM_TRUSTED_KEYS 来解决:
重新执行 make menuconfig, 定位到如下位置
1 | -> Cryptographic API (CRYPTO [=y]) |


清空后的配置菜单显示如下:

然后保存退出,重新执行 make -j$(nproc) 即可。
踩坑二:
1 | make[3]: *** 没有规则可制作目标“debian/canonical-revoked-certs.pem”,由“certs/x509_revocation_list” 需求。 停止。 |
和上面是同样的道理,把 “debian/canonical-revoked-certs.pem” 清空即可。
位置如下:
-> Cryptographic API -> Certificates for signature checking ->

使用 Busybox 创建 initramfs
编译 Busybox
Busybox 是一个集成了一百多个 Linux 命令和工具的软件包,它可以用来创建一个最小的 Linux 系统。
Busybox 的官方网站是: https://www.busybox.net/
Busybox 的源码可以从官方网站下载,也可以使用 Git 下载。
1 | git clone git://git.busybox.net/busybox |
目前最新的版本是 1.37 , 我们把 clone 的代码切换到 1.37 版本。
1 | git checkout remotes/origin/1_37_stable -b 1_37_stable |
Busybox 的编译过程和 Linux Kernel 类似,首先需要进行配置。
1 | make menuconfig |
把 Build static binary (no shared libs) 选项选中,这样编译出来的 Busybox 就是一个静态链接的二进制文件。
它位于 Settings 下。

然后开始编译。
1 | make -j$(nproc) |
编译错误与解决方案:
1 | CC networking/tc.o |
如果你遇到了上述关于 networking/tc.c 的编译错误,可以尝试通过关闭 CONFIG_TC 来避免:

编译完成输出如下:
1 | LINK busybox_unstripped |
然后执行 make install 安装 Busybox。
1 | make install |
输出如下:
1 | ./_install//usr/sbin/ubiupdatevol -> ../../bin/busybox |
Busybox 的二进制文件位于 _install/bin/busybox。
创建 initramfs
initramfs 是一个临时的根文件系统,用于启动 Linux 内核。
首先我们创建一个目录,用于存放 initramfs 的文件。
把 Busybox 的二进制文件和 bzImage 复制到这个目录下。
1 | mkdir -p ~/Desktop/kernel/workspace/initramfs |
在 initramfs 目录下创建一个 bin 目录,并把 busybox 复制到这个目录下。
1 | mkdir -p initramfs/{bin,sbin,etc,proc,sys} |
在 initramfs 目录下创建一个 init 文件,用于启动 Linux 内核。
并给 init 文件添加可执行权限。
1 | touch initramfs/init |
init 是 Linux 内核启动时的第一个进程,它负责初始化系统,并启动其他进程。
我们将 init 的内容设置为如下:
1 |
|
接下来我们需要把 initramfs 目录打包成一个 cpio 归档文件。
这里我们编写一个 Makefile 来完成这个任务。
1 | vim Makefile |
Makefile 的内容如下:
1 |
|
Makefile 要使用 Tab 键缩进,不能使用空格。
设置完成后,workspace 目录结构如下:
workspace 目录结构:
1 | wgxls@server:~/Desktop/kernel/workspace$ tree |
然后执行 make initramfs 即可生成 initramfs.cpio 和 initramfs.img。
initramfs.cpio 和 initramfs.img 是一样的,只是 initramfs.img 是 initramfs.cpio 的压缩版本。
1 | wgxls@server:~/Desktop/kernel/workspace$ file initramfs.cpio |
使用 QEMU 启动内核
QEMU 是一个开源的虚拟机软件,可以模拟多种硬件平台,包括 x86、ARM、MIPS 等。
我们可以使用 QEMU 来启动 Linux 内核。
首先我们需要安装 QEMU。
1 | sudo apt install qemu-system-x86 |
上一节中我们已经写好了 Makefile,现在我们执行 make run 即可启动内核。
启动日志如下:
1 | [ 0.000000] Linux version 6.12.0 (root@server) (gcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.42) #3 SMP PREEMPT_DYNAMIC Fri Nov 22 12:21:34 CST 2024 |
退出 QEMU 的方法是按下
Ctrl + a然后再按下x。
我们已经看到了 “Hello, Linux Kernel!”,这表示我们的内核已经成功启动了。
并且成功启动了 init 进程。
🎉 实验成功 🎉
你已经成功编译并启动了一个 Linux 内核。开启了你的 Linux 内核之旅。


