写点什么

从内核到可启动镜像:0 到 1 构建你的极简 Linux 系统

  • 2025-03-31
    浙江
  • 本文字数:3545 字

    阅读完需:约 12 分钟

从内核到可启动镜像:0到1构建你的极简Linux系统

关注微信公众号:Linux 内核拾遗

文章来源:https://mp.weixin.qq.com/s/y27zD6DPYstdVSoHwkOMsg

一、理解 Linux 系统层级

Linux 生态系统由内核(Kernel)和用户空间(User Space)共同构成。内核作为操作系统核心,直接管理硬件资源和基础服务(进程调度、内存管理、设备驱动等),而用户空间则包含应用程序、系统工具和运行环境。主流通用发行版(如 Ubuntu、CentOS)的本质是在标准内核之上,通过整合以下组件形成完整系统:


  • 基础工具链:GNU Coreutils、gcc、glibc 等

  • 服务管理:systemd 或 SysVinit

  • 软件分发:APT/YUM/DNF 包管理系统

  • 硬件适配:DKMS 动态内核模块支持


本文聚焦于构建一个最小化可启动镜像,该镜像包含定制编译的内核、精简的临时根文件系统(initramfs)和基础 Shell 环境,揭开 Linux 操作系统的神秘面纱。

二、编译 Linux 内核

1. 环境准备与源码获取

我们需要准备好构建环境,这里以 Ubuntu 22.04 为例。首先安装内核编译过程中需要用到的依赖包,然后从 Linux kernel 官网获取内核源代码。


# 安装编译依赖(Ubuntu/Debian)sudo apt update && sudo apt install -y \    build-essential \    libncurses-dev \    flex \    bison \    libssl-dev \    libelf-dev \    git
# 获取内核源码git clone --depth 1 \ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitcd linux
复制代码


如果因为某些魔法导致内核下载很慢,可以尝试使用国内的镜像源,例如清华大学的开源镜像站(https://mirrors.tuna.tsinghua.edu.cn/help/linux.git/):


# 从清华开源镜像站获取内核源码git clone --depth 1 https://mirrors.tuna.tsinghua.edu.cn/git/linux.git
复制代码


接下来我们默认使用 Linux 内核主干分支进行内核编译,如果需要指定版本的话,可以 git clone 的时候使用-b <版本名>来指定,例如-b v6.14,或者是 git clone 完了之后切换到对应的 tag 也行,例如git checkout v6.14

2. 内核配置和优化

接下来是内核编译前的一些配置工作,我们可以在默认配置的基础上做一些调整:


# 生成默认配置make defconfig
# 关键配置调整(可选,看个人需要)scripts/config \ --disable DEBUG_INFO \ # 禁用调试符号(减少体积) --enable VIRTIO \ # 启用虚拟化驱动 --disable MODULES \ # 禁用动态模块加载 --enable STATIC_KEYS \ # 优化内核功能开关 --enable BPF_JIT # 支持eBPF
# 查看配置变更diff -u .config.old .config
复制代码

3. 内核编译

前面准备工作做好之后,就可以愉快地开始我们的内核编译了:


# 并行编译(根据CPU核心数调整)make -j$(nproc) 
复制代码


这个过程比较长,取决于编译环境的核心数,耐心等待即可。过程中如果碰到依赖包缺失,按照错误提示安装然后重新编译即可,或者其他稀奇古怪的错误,直接 google 一下。这里不再赘述。


最后编译得到内核镜像文件:


  • x86_x64 环境:arch/x86_64/boot/bzImage

  • arm64 环境:arch/arm64/boot/Image.gz

三、构建最小化 initramfs

内核编译好后,就可以开始制作我们的镜像根文件系统了。

1. 什么是 initramfs

initramfs(Initial RAM File System)是 Linux 系统启动过程中使用的 临时根文件系统,它存储在内存中,用于在内核加载后、挂载真实根文件系统前完成关键初始化任务。


它区别于传统的 initrd 方案:


  • initrd(旧方案)

  • 基于磁盘映像(如ext2格式)。

  • 需单独分区或文件。

  • 效率较低,已逐步被淘汰。

  • initramfs(现代方案)

  • 基于cpio+压缩,直接嵌入内核或作为独立文件。

  • 通过tmpfs在内存中运行,无需块设备驱动。

  • 支持按需加载文件,更灵活高效。

2. 构造目录结构与设备节点

首先需要构造最基本的根文件系统目录结构和设备节点,例如主流 Linux 发行版中最常见到的 bin、dev、proc、sys 等目录,以及 console、null 等常用设备节点:


mkdir -p initramfs/{bin,dev,proc,sys}cd initramfs
# 创建设备文件sudo mknod dev/console c 5 1 # 控制台设备sudo mknod dev/null c 1 3 # 空设备sudo chown root:root dev/{console,null}
复制代码

3. 集成 BusyBox

BusyBox 是一个高度优化的 多合一 Unix 工具集,它将数百个常用 Unix 工具(如 lscatgrepmountifconfig 等)集成到一个精简的二进制文件中。


为了让我们自制的 Linux 系统在启动后能够执行基本的一些操作,可以将 busybox 集成到我们的镜像文件中。


# 下载并编译wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2tar -xf busybox-1.36.1.tar.bz2cd busybox-1.36.1
# 配置为静态链接make menuconfig# 进入配置界面后,请用以下选项:Settings ---> [*] Build static binary (no shared libs) # 静态编译
# 编译busyboxmake -j$(nproc)
# 部署到initramfsmake install CONFIG_PREFIX=</path/to/initramfs>
复制代码


这里说明一下,我们选择静态方式编译 busybox,目的是将程序的所有依赖库直接打包进二进制文件,避免了 Linux 系统运行时依赖动态库。

4. 编写初始化脚本

根文件系统准备好之后,我们还需要添加一个初始化脚本“init”。它作为 Linux 启动镜像(initramfs)中的 首个用户态进程(PID 1),由内核直接启动,承担着从内核过渡到用户空间的关键桥梁作用,主要任务是为后续系统启动准备必要的运行环境。


cat > init <<'EOF'#!/bin/sh
# 挂载虚拟文件系统mount -t proc proc /procmount -t sysfs sysfs /sysmount -t devtmpfs devtmpfs /dev
# 启动交互Shellexec /bin/shEOFchmod +x init
复制代码

5. 打包与验证

至此,我们的根文件系统已经全部准备完成,最后将其打包到 initramfs.img 镜像文件中。


find . | cpio -H newc -o | gzip > ../initramfs.img
# 检查打包结果file ../initramfs.img # 应显示类似内容:../initramfs.tar.gz: gzip compressed data, from Unix, original size modulo 2^32 2206208
复制代码

四、制作可启动 ISO 镜像

1. 什么是 ISO 文件

ISO 文件是一种标准的光盘镜像格式(遵循 ISO 9660 文件系统规范),通常用于封装完整的可启动操作系统或软件集合。在 Linux 系统构建中,ISO 文件的核心作用是将内核(vmlinuz)、初始内存盘(initramfs.img)和引导程序(如 GRUB)等关键组件打包成一个可物理刻录(光盘/USB)或虚拟机加载的独立镜像。


  1. 引导程序(如 GRUB)从 ISO 中加载内核和 initramfs.img 到内存;

  2. 内核解压并运行 initramfs.img 中的临时根文件系统,执行硬件初始化、驱动加载等任务;

  3. 最终挂载 ISO 内的持久化文件系统(如 Live CD 的 squashfs)或外部存储设备,完成系统启动。

2. 构建 ISO 目录结构

这里主要是构建 boot 目录,然后将前面编译或者构建好的内核镜像文件(bzImage 或者 Image.gz)、根文件系统镜像文件(initramfs.img)添加到 boot 目录中,然后配置参数(grub.cfg):


mkdir -p iso/boot/grub
# x86_64cp ../linux/arch/x86_64/boot/bzImage iso/boot/vmlinuz# or arm64cp ../linux/arch/arm64/boot/bzImage iso/boot/vmlinuz
cp ../initramfs.img iso/boot/initrd
# 编写GRUB配置cat > iso/boot/grub/grub.cfg <<'EOF'menuentry "Custom Linux" { linux /boot/vmlinuz console=ttyS0 root=/dev/ram0 rw initrd /boot/initrd}EOF
复制代码

3. 生成 ISO 文件

最后借助 grub-mkrescure 工具生成 ISO 镜像文件(custom-linux.iso):


# 安装工具依赖包apt install mtools xorriso
# 生成ISOgrub-mkrescue -o custom-linux.iso iso/
# 验证ISO结构xorriso -indev custom-linux.iso -ls
复制代码

五、镜像测试

这里我们以 VMWare 为例来验证我们制作的 Linux 系统 ISO 镜像:


1、创建虚拟机,选择我们制作好的 ISO 镜像文件(custom-linux.iso):



2、选择操作系统的配置,按需选择即可:



3、完成虚拟机创建:



4、启动虚拟机:




5、验证基本的 busybox 命令:



最终我们得到了一个最简单的 Linux 系统镜像,还能够支持简单的 busybox 命令!

六、迈向真正的 Linux 发行版

前面我们只做的 Linux 系统镜像,距离真正的 Linux 发行版还有很大一段路要走,但是好消息是我们已经掌握了最核心的方法步骤,并且得到了一个可以在虚拟机环境下运行和验证的 ISO 镜像,我们可以在此基础上逐步去完善我们的镜像,最后得到一个完整的发行版。


  1. 建立基础运行时环境:移植动态链接库(glibc)、时区数据、基础配置文件(/etc/passwd)等。

  2. 实现包管理系统

  3. 设计元数据格式(包名、版本、依赖)。

  4. 编写安装脚本(pre/post install hooks)。

  5. 创建本地软件仓库。

  6. 添加网络与 SSH 服务。

  7. 构建自动化工具链:使用 Makefile 或 Shell 脚本实现内核编译、文件系统打包、ISO 生成的流水线。

  8. 支持持久化存储:开发分区工具,支持 ext4/XFS 文件系统初始化,实现根文件系统切换。

  9. 创建安装程序:开发交互式 CLI 工具,支持磁盘分区、软件包选择、引导配置。


关注微信公众号:Linux 内核拾遗

文章来源:https://mp.weixin.qq.com/s/y27zD6DPYstdVSoHwkOMsg

发布于: 刚刚阅读数: 5
用户头像

聚沙成塔 2023-01-12 加入

分享Linux内核开发相关的编程语言、开发调试工具链、计算机组成及操作系统内核知识、Linux社区最新资讯等

评论

发布
暂无评论
从内核到可启动镜像:0到1构建你的极简Linux系统_ISO 镜像文件_Linux内核拾遗_InfoQ写作社区