☰
NodeOS 文件系统布局全解析:系统目录、用户 $HOME 与启动体系
2026/9/29 2:30:40 网站建设 项目流程
  • 操作系统
  • 嵌入式

【免费下载链接】NodeOS

Lightweight operating system using Node.js as userspace

项目地址:https://gitcode.com/gh_mirrors/no/NodeOS
点击查看免费下载

NodeOS 是一个以 Node.js 作为用户态、用 npm 作为包管理器的轻量级操作系统(详见 README.md)。在这样一个"没有全局服务、没有全局模块、没有全局命令"的系统里,文件系统如何组织,直接决定了包的安装方式、服务的运行方式和用户的隔离方式。本文以仓库设计文档 docs/FileSystem.md 为核心骨架,结合 docs/root.md、docs/init.md、docs/asgard.md 等关联文档,系统讲解 NodeOS 的目录设计原则、系统目录与用户目录的边界、内核挂载点,以及 root 用户如何借助这套布局完成系统启动。读完本文,你将掌握 NodeOS 文件系统的完整心智模型,并能据此理解npkg安装包、服务配置与日志、以及 init/asgard 之间的目录协作关系。

从整体架构看文件系统的位置

NodeOS 的开发按分层进行,各层分别对应文件系统的一个组成部分(详见 README.md 的 "Introduction" 部分):

  • barebones:定制 Linux 内核 + initramfs,启动后进入 Node.js REPL;
  • initramfs:初始化内存环境,负责挂载用户分区并启动系统;
  • usersfs:多用户环境,行为与传统操作系统一致。

下图(doc/NodeOS Layer 2 - initramfs.png)展示了 initramfs 层:在 barebones 基础软件栈之上,mount-filesystems负责挂载文件系统,usrbinenv负责环境准备,这一层正是文件系统布局的"搬运工"——它决定了后续挂载到哪个根、哪些用户目录会被识别。

NodeOS Layer 2 initramfs 架构:mount-filesystems 负责挂载文件系统

而最终承载用户与应用的则是 usersfs 层(doc/NodeOS Layer 3 - usersfs.png),其中可以看到root与普通用户目录的划分,root下运行着 PalmTree(服务启动器)、bin-getty、logon 等系统组件,用户侧则是 npm、nsh 等工具——这正是本文要详解的目录布局落地形态。

NodeOS Layer 3 usersfs 架构:展示 root 与普通用户目录的划分

系统目录:为兼容 libc 而保留的"私有"目录

NodeOS 基础文件系统的布局遵循一个核心原则:传统 Linux 的系统级目录被视为"私有"目录,仅为了兼容当前使用的 libc 而保留。它们在启动后由系统自身管理,用户不应直接写入。

/bin <-- contains latest node executable /lib /usr /etc

也就是说:

  • /bin中放置的是最新版 Node.js 可执行文件,而非一堆系统命令——NodeOS 不需要/bin/ls、/bin/cp这类传统二进制,命令是各用户自己安装的(见下文"用户目录");
  • /lib、/usr、/etc的存在更多是满足 glibc/musl 等 C 运行库对标准路径的隐式依赖,让现有 Node.js 二进制和原生模块能够正常工作;
  • 所有用户可编辑的内容都应该放到用户目录中,而不是这些系统目录。

设计文档 docs/product.md 将 FileSystem 定位为"技术与产品的混合体":目录的挪动是为了技术上更好地组织系统,但又不希望文件系统对用户显得陌生——这解释了为何保留标准 Linux 路径形态、同时把可写空间全部收敛到用户目录。

用户目录:root 与普通用户的分界

所有用户可编辑的内容位于用户目录中,root 用户的 home 目录使用标准位置/root,非 root 用户则位于/home下:

/root <-- root user /home <-- non-root users

root 用户是特殊的:它负责启动整个系统。普通用户目录则彼此隔离,每位用户在自己的$HOME内拥有完整的软件环境。这一设计在 docs/root.md 中有更详细的展开,我们将在"root 目录与系统启动"一节继续说明。

内核提供的文件系统:挂载在常规位置

其他由内核提供的文件系统被挂载在它们的常规位置,用户可以直接访问,但数据性质各不相同:

/dev <-- devfs /proc <-- procfs /sys <-- sysfs /tmp <-- tmpfs
  • /dev(devfs):设备文件,对应系统的各种硬件设备节点;
  • /proc(procfs):进程信息,/proc/cpuinfo等内核与进程状态接口;
  • /sys(sysfs):内核对象与驱动的 sysfs 视图;
  • /tmp(tmpfs):内存文件系统,重启后内容即失。

值得留意的是,尽管/tmp是内核提供的 tmpfs,NodeOS 依然在用户目录中为每个用户保留了tmp/(临时数据),这是因为系统性的临时空间与用户任务的临时空间在生命周期与权限语义上并不相同。

用户目录详解:每个 $HOME 就是一个小型根文件系统

NodeOS 最颠覆性的设计是:没有全局的服务、模块或命令。曾经属于系统级的目录,如etc、var,现在都变成用户局部的。每个用户的$HOME结构如下:

$HOME/ bin/ <-- executable commands ls, cp, mv lib/ node_modules/ <-- modules installed by npkg log/ <-- logs from init jobs etc/ <-- configuration files var/ <-- persistent data tmp/ <-- ephemeral data

各目录职责细化如下:

目录职责说明
bin可执行命令包含ls、cp、mv等命令,在npkg install时创建命令链接
lib模块库存放处lib/node_modules存放由npkg安装的模块
log日志存放 init 任务(服务和作业)产生的输出日志
etc配置存放服务和作业的本地配置值
var持久数据存放服务和作业的持久化数据
tmp临时数据存放服务和作业的临时数据

原文档特别强调:这些目录的约定是被npkg命令假定并使用的。也就是说,npkg install会把可执行文件软链到$HOME/bin、把模块放进$HOME/lib/node_modules;服务管理器会把日志写入$HOME/log、配置放在$HOME/etc、持久数据存在$HOME/var。理解这一约定,是理解 NodeOS"每个用户一套环境"的钥匙——不同用户安装同一包互不干扰,因为各自的bin/lib/etc互不相同。

root 目录与系统启动:init 与 asgard

root 用户与普通用户一样遵循$HOME布局,但额外承担启动职责。其最小目录集合为(docs/root.md):

/root/ bin/ init <-- boots the system asgard <-- service manager started by init lib/ <-- installed node_modules for init/asgard log/ <-- log files from init and other root services var/ <-- persistent data for root services

即 root 的bin/中安装着init(负责启动系统)与asgard(由 init 启动的服务管理器)。root 目录至少需要上述内容,通常还会包含其他对启动系统有帮助的模块。

init 进程与 PID 1

内核加载完成后,会把控制权交给一个通常被称为init process的进程。该进程拥有 PID 1,必须启动系统的其余部分;如果 init 未能启动系统,内核要么 panic,要么机器"什么也不做"。

传统 Linux 上 init 位于/sbin/init,若启动时不指定,内核会自动在该位置查找。但也可以在启动时通过向内核传递INIT=<path>参数,指定任意进程作为 PID 1。NodeOS 正是利用了这一点:

  • NodeOS 在/sbin/init处没有进程;
  • 它的 init 只是安装到/root/bin/的一个可执行文件;
  • init 本身是一个 Node.js 模块,其package.json中包含bin键;
  • 任何带bin键的 Node 模块都可以充当 NodeOS 的 init,只是项目提供一个"够用且最小"的 init 模块。

init 的双重职责

docs/init.md 描述了 init 的设计:它会是一个"超简单"的进程,只做两件事:

  1. 周期性地收割死掉的子进程(reap dead children);
  2. 启动根服务管理器 asgard。

为什么需要收割僵尸进程:Linux 的机制是,当父进程死亡后,其子进程会被收养为 PID 1 的子进程。当这些子进程退出时,它们的 PID 号与退出状态会记录在内核进程表中;作为父进程的 init 需要周期性地调用wait或waitpid来清空进程表。已退出但尚未被清空的进程被称为zombie(僵尸进程)。由于 init 会收养大量子进程,如果它们退出后无人清收,系统就会"僵尸泛滥",因此 init 必须扮演"死神"(grim reaper)的角色。

服务管理器 asgard 与 PalmTree

init 就绪后,会把控制权移交给服务管理器。设计文档 docs/asgard.md 描述的 asgard 是"任务运行型服务",提供两个底层抽象:

  1. task(任务):一个必须运行的真实进程;
  2. queue(队列):任务的有序列表。

其行为特征包括:任务一旦加入队列即被运行;同一队列内的任务顺序执行;不同队列并行执行;空队列只是等待新任务;对队列操作的支持有限。

需要注意的是,asgard 页面已明确标注Deprecated(弃用),NodeOS 现采用PalmTree作为服务启动器(见 docs/en/Service-Starter-(PalmTree).md.md) 与 docs/services.md)。PalmTree 使用/etc下的palmtree.json文件,它是一个 JSON 编码的对象数组,每个对象最少包含要执行的命令,可选name与args:

[ { "command": "plexdl", "name": "PlexDL", "args": ["beta-gui"] } ]

启动时 PalmTree 会按此配置运行命令;增加/移除开机服务只需编辑该 JSON 数组,也可以在 Node.js 中require该文件、修改后再序列化写回,实现编程式管理。这与本文件系统文档呼应:etc/用户局部配置目录正是palmtree.json这类配置的落点。

与源码实现的印证:分层构建与镜像挂载

这套文件系统设计在仓库构建层面得到了印证。根目录 package.json 将构建拆分为三个核心依赖:

  • nodeos-barebones(内核与基础层)
  • nodeos-initramfs(初始化内存文件系统,含挂载逻辑)
  • nodeos-usersfs(用户态文件系统)

这与 README 中的三层结构一一对应。此外,lib/index.js 中的prepareCommandLine展示了各平台启动时如何挂载这些文件系统镜像:

  • img平台:-hda bootfs.img+-hdb usersfs.img(双磁盘:启动文件系统 + 用户文件系统);
  • iso平台:-cdrom bootfs.iso+-hda usersfs.img;
  • qemu平台:--kernel kernel+--initrd initramfs.cpio.gz+usersfs.img作为根盘,追加root=/dev/sda、ip=dhcp等内核参数。

从源码结构看,bootfs(启动镜像,含内核与 initramfs)与usersfs(用户文件系统,含各用户$HOME)始终被分开管理,用户数据与系统核心互不混杂,正是本文所述"系统目录私有化、用户目录承载一切可写内容"原则的落地体现。

总结

  • NodeOS 将传统 Linux 系统目录(/bin、/lib、/usr、/etc)降级为"仅供 libc 兼容"的私有区域,所有用户可编辑内容进入用户目录;
  • root 用户在标准/root,非 root 用户在/home,每位用户的$HOME内含bin/lib/log/etc/var/tmp完整目录集,并被npkg等工具默认使用;
  • 内核文件系统(devfs、procfs、sysfs、tmpfs)仍挂载在常规位置;
  • /root/bin中的init作为 PID 1 收割僵尸进程并启动服务管理器,最终由 PalmTree(或早期设计中的 asgard)拉起全部用户服务;
  • 构建层面通过 barebones / initramfs / usersfs 三层依赖与 bootfs、usersfs 双镜像,保证系统核心与用户文件系统物理分离。

这套"无全局、纯用户局部"的文件系统设计,是 NodeOS"让 npm 提供其余一切"理念的基石:没有中心化的包目录,没有系统级守护进程,每个用户在自己的$HOME里拥有完整、隔离、可随时重建的软件环境。

  • 操作系统
  • 嵌入式

【免费下载链接】NodeOS

Lightweight operating system using Node.js as userspace

项目地址:https://gitcode.com/gh_mirrors/no/NodeOS
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询