编译镜像

  1. 下载源码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.19.303.tar.xz
tar -xvf linux-4.19.303.tar.xz
```

2. 修改编译配置


执行 `make menuconfig` 进入 tui 配置界面,需要开启 `Compile the kernel with debug info` 和关闭 `Randomize the address of the kernel image`

```
Kernel hacking  ---> 
    [*] Kernel debugging
    Compile-time checks and compiler options  --->
        [*] Compile the kernel with debug info
        [*]   Provide GDB scripts for kernel debuggin


Processor type and features ---->
    [] Randomize the address of the kernel image (KASLR)
```

3. 安装编译时会用到的工具

```shell
sudo apt-get install libncurses5-dev   openssl libssl- dev 
sudo apt-get install build-essential openssl
sudo apt-get install pkg-config
sudo apt-get install libc6-dev
sudo apt-get install bison
sudo apt-get install flex
sudo apt-get install libelf-dev
sudo apt-get install zlibc minizip
sudo apt-get install libidn11-dev libidn11
```

4. 编译 `make -j<编译用到的cpu核心数>`

5. 编译完成后在 `arch` 目录下找到自己的 cpu 架构下对应的目录。里面的 `boot` 中包含 `bzImage`  `vmLinux`。其中 `bzImage` 是一个 `gzip` 自解压的 Linux 压缩镜像。`vmLinux` 是未压缩的镜像,它包含调试信息。

### 制作 rootfs

rootfs 提供了 Linux 运行所需要的文件,例如关键的目录结构、shell命令、系统配置、动态链接库等。Linux 初始化过程中需要这个文件系统作为 initramfs (内存之上的文件系统) 来引导系统启动。

busybox 将多个工具(如 ls、cp、mv、rm、cat、echo 等)集成到一个单一的可执行文件中,可以通过符号链接(symlink)或硬链接(hard link)来调用不同的工具。

所以我们可以利用 busybox 来作为 rootfs 的一部分。

1. 下载 busybox,并解压

```shell
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xvf busybox-1.36.1.tar.bz2
```

2. 进入 busybox 目录,修改 busybox 编译配置

```shell
$ make menuconfig
-> Settings
 --- Build Options
  [*] Build static binary (no shared libs)
```

3. 编译 busybox

```shell
make && make install
  1. 创建关键目录
1
mkdir bin dev proc sys tmp
  1. 创建 init 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/bin/sh
# 指定解释器为 /bin/sh,即 Bourne shell 或其兼容版本

# 打印一条调试信息,表示初始化脚本开始执行
echo "{==DBG==} INIT SCRIPT"

# 创建 /tmp 目录。这个目录通常用于存放临时文件
mkdir /tmp

# 挂载 proc 文件系统到 /proc 目录。proc 文件系统提供了内核和进程信息
mount -t proc none /proc

# 挂载 sysfs 文件系统到 /sys 目录。sysfs 文件系统提供了设备和内核模块的信息
mount -t sysfs none /sys

# 挂载 debugfs 文件系统到 /sys/kernel/debug 目录。debugfs 文件系统用于调试信息和调试工具
mount -t debugfs none /sys/kernel/debug

# 挂载 tmpfs 文件系统到 /tmp 目录。tmpfs 是一个基于内存的文件系统,适合存放临时文件
mount -t tmpfs none /tmp

# 运行 mdev -s 命令。mdev 是一个轻量级的设备管理器,通常用于嵌入式系统中。-s 选项表示扫描 /sys 目录以发现和配置设备节点
mdev -s

# 打印一条调试信息,显示系统启动所花费的时间。/proc/uptime 文件的第一列是系统启动后的秒数。cut -d' ' -f1 /proc/uptime 提取这个值
echo -e "{==DBG==} Boot took $(cut -d' ' -f1 /proc/uptime) seconds"

# 使用 exec 命令启动一个新的 shell(/bin/sh),并替换当前的脚本进程。exec 命令不会创建新的进程,而是用指定的命令替换当前进程。这意味着脚本执行完毕后,用户将进入一个交互式 shell 环境
exec /bin/sh
  1. 基于上面编译和创建文件制作 rootfs 镜像
1
2
# 将当前目录下的所有文件以 newc 的格式归档到 rootfs.img 文件中。
find . | cpio -o --format=newc > ./rootfs.img