← 返回信息流
AI 资讯Hacker News·3 小时前

Boot Naked Linux:无需安装即可直接启动的Linux发行版

原标题:Boot Naked Linux

速览

Boot Naked Linux是一款特殊的Linux发行版,其核心特性是无需进行传统安装即可直接启动运行。该发行版通常用于快速测试、数据恢复或临时计算环境,用户可以直接从USB或光盘引导进入系统。这种设计大大简化了Linux的使用门槛,特别适合需要快速部署临时环境的场景。

AI 深度解读

Boot Naked Linux:极简 Linux 启动实验深度解读

背景

在个人计算机发展的早期阶段,计算体验与今天截然不同。那时的计算机并非像现代服务器或桌面系统那样全天候运行(24/7),用户在使用完毕后通常会直接关机。当需要再次使用时,只需按下电源键,系统便会在短短一秒钟内从磁盘驱动器加载所需内容并恢复工作状态。

然而,随着技术的演进,这种“即开即用”的体验逐渐消失。尽管在 2000 年代初,固态硬盘(SSD)的引入曾短暂地让启动速度变得极快,但科技行业随后引入了复杂的软件栈、后台服务、图形界面和系统守护进程,抵消了硬件带来的性能红利。即便是在拥有 16 核处理器和高速 SSD 的现代“怪兽级”机器上,完成完整的系统启动并进入可用状态仍需花费一分钟甚至更久。

出于对这种“臃肿”启动过程的不满,作者决定尝试一种替代方案:保留 Linux 内核,但剥离所有不必要的组件,探索一种极简的启动方式。这一实验旨在还原计算机启动最本质的过程,验证在剥离了现代发行版庞大的 initrd(初始 RAM 磁盘)后,系统能否以更轻量的方式运行。

核心内容

1. 极简 Init 程序的编写

Linux 系统启动后的第一个关键步骤是运行一个名为 init 的程序,它负责加载其他进程和配置。作者指出,init 本质上只是一个普通的可执行文件或脚本。为了实验,作者用 C 语言编写了一个极简的 init.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/reboot.h>

int main(int argc, char **argv) {
    fprintf(stderr, "Hello from init.c!");
    reboot(RB_POWER_OFF);
}

这段代码的功能极其简单:打印一条消息,然后调用 reboot(RB_POWER_OFF) 有序地关闭虚拟机。作者特别提到,如果 init 进程直接退出,Linux 内核会发生恐慌(Kernel Panic)。为了避免陷入忙等待或无限睡眠,使用 reboot 系统调用是一种优雅地终止虚拟机的方法。

2. 现代 Linux 启动流程解析

作者梳理了截至 2026 年(Linux 6.8 左右版本)的现代 Linux 启动流程,这是一个多阶段过程:

  1. 引导加载程序(Boot Loader):加载内核和一个名为 initrd 的虚拟文件系统。
  2. 内核解压:内核将 initrd 解压到内存中,形成 initramfs(基于 RAM 的根文件系统),以便初始化工具在此环境中运行。
  3. 寻找 Init 程序
    • 内核首先查找 initramfs 中的 /init 文件(或通过内核参数 rdinit= 指定的文件)。如果存在,则运行它,该进程接管初始化工作。
    • 如果不存在,则回退到传统流程:挂载由 root= 参数指定的根分区,在 /dev 挂载 devtmpfs,然后运行根分区中的 /init(或通过 init= 参数指定)。
  4. 失败处理:如果上述步骤失败或 init 进程退出,内核将发生恐慌。

大多数现代发行版使用第一种分支,提供一个较大的 initrd 以加载模块和固件。作者指出,其 PC 上的 initrd 文件高达 73MB,包含 2163 个文件,这显然是过度设计。

3. 构建微型 Initrd

为了简化启动过程,作者决定替换整个 initrd。通过将 C 代码静态编译(包含所有依赖库),可以创建一个仅包含单个文件(即编译后的 init 二进制文件)的 initrd

构建命令如下:

gcc -static init.c -o init
echo 'init' | cpio -o --format=newc | gzip -c > initrd

这里使用了 cpio 工具来创建归档。作者幽默地指出,cpio 是一个古老且命令行晦涩的程序,其管道操作方式看似怪异,但考虑到它比 tar 和 shell 文件名通配符都古老,这种设计是可以理解的。

调试提示

  • 如果看到 Initramfs unpacking failed: no cpio magic,说明 cpio 格式、压缩方式或内核兼容性有问题。
  • 如果看到 check access for rdinit=/init failed: -2,通常意味着 initramfs 未正确加载或二进制文件位置错误(-2 对应 ENOENT,即文件未找到)。
  • 如果看到 Trying to unpack rootfs image as initramfs... 且后续无报错,则是一个好迹象。

4. 在虚拟化环境中测试

由于在真实硬件上测试涉及繁琐的 USB 切换,作者使用 QEMU/KVM 进行虚拟化实验。

  • 内核准备:复制当前系统的 /boot/vmlinuz 并更改权限,或者自行编译精简版内核。

  • 启动命令

    kvm -m 1G -nographic -kernel vmlinuz \
    -initrd initrd -append "console=ttyS0"
    

    其中 -nographic-append "console=ttyS0" 选项用于通过串行控制台监控 stderr 输出,而非弹出图形界面。

  • 启动输出: 内核成功解压 initrd 并运行 init,输出如下:

    [ 0.000000] Linux version 6.8.0-111-generic ...
    [ 0.489390] Trying to unpack rootfs image as initramfs...
    [ 0.805419] Run /init as init process
    Hello from init.c!
    [ 0.807535] reboot: Power down
    

5. 设备访问:挂载 devtmpfs

/init 运行时,根文件系统尚未挂载,因此默认情况下没有设备节点可用。为了访问存储设备(如 QEMU 模拟的 /dev/sda),必须在 init 程序中手动激活内核机制 devtmpfs

作者修改了 init.c,增加了挂载 devtmpfs 和读取磁盘镜像前几个字节的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/reboot.h>
#include <arpa/inet.h>

int main(int argc, char **argv) {
    fprintf(stderr, "Hello from init.c!\n");
    // 挂载 devtmpfs 以提供设备节点
    mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);
    
    // 打开 QEMU 提供的磁盘设备
    int fd = open("/dev/sda", O_RDWR);
    uint32_t buffer[2];
    read(fd, buffer, sizeof(buffer));
    close(fd);
    
    fprintf(stderr, "Read %08x %08x\n", ntohl(buffer[0]), ntohl(buffer[1]));
    reboot(RB_POWER_OFF);
}

为了测试,作者创建了一个包含随机数据的磁盘镜像 diskimage,并修改了 KVM 启动命令以挂载该镜像:

kvm -m 1G -nographic -kernel vmlinuz \
-initrd initrd -append "console=ttyS0" \
-no-reboot -hda diskimage

最终,系统成功读取了磁盘镜像的前 8 个字节,证明了在极简 initrd 中手动挂载设备文件系统的可行性。

关键要点

  • 启动速度悖论:尽管硬件(SSD、多核 CPU)性能大幅提升,但由于软件栈的复杂化,现代 Linux 系统的启动时间并未显著缩短,甚至可能比早期系统更慢。
  • **Initrd 的冗余性
查看原文 →nick.zoic.org