内容提要
本文记录了作者在Lichee Pi 4A上运行NixOS的过程,介绍了NixOS的启动流程和组件作用,总结为一次有趣的学习经历。
延伸解读
NixOS 移植的独特挑战
与常见的 ARM 开发板不同,Lichee Pi 4A 采用 RISC-V 架构,其启动链涉及 OpenSBI、U-Boot SPL 等组件,且 NixOS 的声明式构建方式导致现有移植方案无法直接套用。作者不得不从 RevyOS 中提取硬件相关部分,再与 NixOS 的 rootfs 组合,过程中还遇到了标准工具链编译内核的 bug,这凸显了 RISC-V 生态在软件适配上的不成熟。
NixOS 启动流程的三个阶段
启动日志显示,系统首先由 OpenSBI 完成硬件初始化,接着进入 NixOS Stage 1(initrd 阶段),内核加载必要驱动并挂载根文件系统,最后是 Stage 2,执行 activation 脚本配置 /etc、扩容分区等,之后才启动 systemd。这种分阶段设计使得 NixOS 能在挂载根文件系统前完成复杂准备,但也增加了调试难度,尤其是当启动失败时,问题可能出现在任一阶段。
init 与 activate 脚本的分工
NixOS 的 init 程序是一个 shell 脚本,它主要负责将 /nix/store 重新挂载为只读,然后调用 activate 脚本。activate 脚本则承担了大部分系统配置工作,包括创建 /etc 下的文件、设置用户组、生成安全包装器等。这种设计将启动过程拆分为两个脚本,使得配置逻辑更清晰,但也意味着任何配置错误都可能导致系统无法正常启动,需要仔细检查脚本执行日志。
文件树差异带来的调试启示
NixOS 根目录下仅有 /boot 和 /nix 等少数文件夹,与传统发行版遵循的 FHS 标准大相径庭。这种结构源于其将所有软件包存储在只读的 /nix/store 中,其他目录均在运行时动态生成。初次接触时容易误以为镜像不完整,但实际这是 NixOS 实现声明式配置和可回滚更新的基础。理解这一点有助于在移植或调试时快速定位问题,避免被表面现象迷惑。
Q&A
NixOS 在 Lichee Pi 4A 上的启动流程分为哪几个阶段?
启动流程分为三个阶段:OpenSBI、NixOS Stage 1 和 NixOS Stage 2。OpenSBI 阶段进行硬件初始化;Stage 1 由 initrd 完成,加载内核模块、检查并挂载根文件系统;Stage 2 运行 activation script,配置系统并启动 systemd。
NixOS 的根文件系统结构和传统 Linux 发行版有什么不同?
NixOS 根目录下只有 /boot、/nix、/lost+found 和 /nix-path-registration 等少数文件夹,而传统发行版遵循 FHS 标准,有 /bin、/etc、/home 等众多目录。NixOS 将所有数据存放在只读的 /nix/store 中,其他目录在运行时动态创建。
NixOS 启动过程中的 init 程序有什么作用?
init 是 NixOS 启动时的第一个用户态程序(PID 1),对应 Stage 2。它是一个 shell 脚本,负责将 /nix/store 重新挂载为只读,然后执行 activate 程序进行系统配置,最后启动 systemd。
activate 程序在 NixOS 启动时做了哪些事情?
activate 程序负责配置系统,包括挂载 /proc、/sys 等目录,创建 /home、/root 等目录,生成 /etc 下的配置文件,设置用户和组,创建安全包装器,并将当前系统配置链接到 /run/current-system。
为什么 NixOS 的根文件系统下只有很少的文件夹?
因为 NixOS 将所有系统数据存放在 /nix/store 中并挂载为只读,其他文件夹如 /etc、/bin 等在运行时动态创建。这是实现声明式配置、可回滚更新和多版本共存的基础。
在 Lichee Pi 4A 上移植 NixOS 时,作者遇到了哪些困难?
作者从 6 月 13 日折腾到 7 月 3 日,学习了 U-Boot、OpenSBI、SPL Flash 等新技术,参考了 Fedora 移植方案,请教了多位开发者,最终编译出镜像但初次启动失败,直到 8 月 6 日才成功启动。