深入理解 Linux 启动过程 | QEMU 启动 linux 内核和自制根文件系统
故事开始的地方,深入 Linux 系统的启动流程,自己编译内核并制作根文件系统,并使用 QEMU 模拟启动.
跟我一起来到故事开始的地方,深入 Linux 系统的启动流程,自己编译内核并制作根文件系统,并使用 QEMU 模拟启动。
前置知识
昨天看到阮老师两篇文章 《**计算机是如何启动的?》和 《Linux 的启动流程**》,对计算机的启动流程有了更加深入的理解,正好最近在做国产申威处理器的虚拟化支持性调研,称此机会深入了解一下 Linux 系统的启动流程,并使用 QEMU 模拟这一流程。
说明:本文介绍的方法同样可用于内核调试,但侧重于介绍 使用 QEMU 模拟 Linux 的启动流程 。本文核心内容参考了 USTC 2021年春季『操作系统原理与设计』 课程实验,结合网络文献和自己的实验整理而来。
如果对于 Linux 的启动流程不够熟悉,可以先看一下上面提到的文章,之后回到本文继续。
看过文章后应该对启动流程有了大概认识,本文会介绍自制一个简单的根文件系统,即 initramfs
(基于 ramfs
的临时文件系统,一种以 cpio
格式压缩后的 rootfs
文件系统),如果对这个概念不太理解,可以来看一下 《 USTC 2021年春季操作系统原理与设计 课程实验一:编译运行Linux内核并通过QEMU+GDB调试》中 实验说明 的『先导知识部分』。
本文会分别使用一个 helloworld 程序 和 busybox 分别生成根文件系统并启动。
简单说一下环境:
- 硬件平台: Lenovo 台式机
- 操作系统:
Ubuntu 20.04.3 LTS
- 系统内核:
5.11.0-40-generic
- QEMU:
QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.18)
- 实验内核:
4.9.263
- busybox:
busybox-1.32.1
模拟启动
下面介绍使用 QEMU 模拟启动内核和根文件系统的方法,让 Linux 启动流程有一个更加具体的认识。为了模拟启动,需要准备编译好的内核 bzImage
和根文件系统,下面分别介绍。
编译内核
本文使用 linux-4.9.263
版本内核为例,首先获取内核源码:
1 |
|
准备好编译环境后,开始对接下来的编译做一个配置,这里提供两种方案,选一即可。
- 方案一: 精简配置,减少不必要的驱动编译(速度快,存储小)
1 |
|
- 方案二: 内核配置(
make menuconfig
)详述(编译时间较长,占空间)
1 |
|
有了内核编译配置,即可开始编译:
1 |
|
制作根文件系统
在这里也提供两种方案,后面可以分别启动,实测均可启动成功。
- 方案一:自制简单 helloworld 程序:
这里写一个简单的 helloworld 程序,正常启动后在终端打印 hello world!
,源码如下:
1 |
|
之后使用静态链接编译,使用 cpio
制作成 rootfs
1 |
|
- 方案二:使用busybox生成:
BusyBox是一个遵循GPL协议、以自由软件形式发行的应用程序。Busybox在单一的可执行文件中提供了精简的Unix工具集,可运行于多款POSIX环境的操作系统,例如Linux(包括Android)、Hurd、FreeBSD等等。由于BusyBox可执行文件的文件比较小,使得它非常适合使用于嵌入式系统。作者将BusyBox称为“嵌入式Linux的瑞士军刀”。 —— BusyBox By Wikipedia
首先获取源码:
1 |
|
之后编译并安装:
1 |
|
现在我们已经有了 busybox 相关的源程序,下面开始准备根文件系统:
1 |
|
这里的
mknode
分别创建了一个面向块设备和一个面向字符设备的特殊文件。
将以下内容写入 init
1 |
|
下面开始生成 rootfs
1 |
|
启动
经过上述准备,终于要启动了!
根文件制作过程如果是采用了 方案一 ,使用下面命令启动:
1 |
|
可以看到启动成功后打印出了 hello world。
如果采用 方案二 ,使用下面命令启动:
1 |
|
使用 busybox 制作的 rootfs 提供了一些基础的命令可供使用。
总结
为了在 QEMU 中模拟 Linux 的启动流程,在网上找了许多教程,踩了很多坑,最后找到的 USTC 实验说明真是帮助很大,做完后对 Linux 启动流程有了更加深刻的理解,果然在计算机的世界里,必须亲眼看到才能真正正确的理解。希望这份教程能够帮到你。
参考文献
- USTC 操作系统原理与设计 Operating System Principles and Implementation 2021年春季
- 实验一:编译运行Linux内核,制作initramfs,并通过qemu+gdb调试
- mknod用法以及主次设备号
- Linux 的启动流程 By 阮一峰
- 计算机是如何启动的? By 阮一峰
- BusyBox By Wikipedia
- 第一步,用qemu启动linux内核,从跑个Helloworld开始
- 在qemu上运行BusyBox
- 编译内核出现:cc1: error: code model kernel does not support PIC mode
- 错误: fatal error: bits/libc-header-start.h: No such file or directory #include <bits/libc-header-start.h>
- qemu启动Linux内核
- QEMU + Busybox 模拟 Linux 内核环境
- Qemu 模拟环境 By CTF Wiki
- Linux 内核编译步骤及配置详解