Moxnox 1.0:运行于 Btrfs 之上的类 NT、兼容 POSIX 的操作系统
摘要
Moxnox 1.0 是一个类似 NT、兼容 POSIX 的业余操作系统,运行于 btrfs 文件系统之上,由约 130,000 行 C++ 代码编写而成,支持 amd64 和 aarch64 架构,并且能够自举。
查看缓存全文
缓存时间: 2026/10/28 01:51
maharmstone/moxnox
来源:https://github.com/maharmstone/moxnox
Moxnox v1.0
Moxnox 是一个类似 NT、兼容 POSIX 的业余操作系统,运行于 btrfs 之上,并且 能够自举。这意味着:
- 它的设计(例如系统调用的选择)以 Windows NT 为蓝本……
- ……但同时,它应该能够运行针对类 Unix 系统编写的软件, 前提是这些软件已为它重新编译,并且它附带 完整的 GNU 基础系统
- 它已经足够成熟,可以在 Moxnox 上构建 Moxnox
- 而且它运行在大家最喜欢的 Linux 文件系统上
1.0 版本约有 130,000 行 C++ 代码,可在 amd64 和 aarch64 上运行。
btrfs 代码可以满足基本用途,但尚未经过充分的实战检验。 请不要尝试挂载任何不能随意丢弃的文件系统。
截图
运行
要在 qemu 中测试 Moxnox,请下载 moxnox-amd64-1.0.img.gz (https://github.com/maharmstone/moxnox/releases/download/v1.0/moxnox-amd64-1.0.img.gz) 和 moxnox-kernel-amd64-1.0.efi (https://github.com/maharmstone/moxnox/releases/download/v1.0/moxnox-kernel-amd64-1.0.efi)。运行 gunzip moxnox-amd64-1.0.img.gz 解压镜像。
然后执行:
qemu-system-x86_64 -M q35 -enable-kvm -cpu host -m 1024 \ -smp cores=4,threads=1 \ -kernel moxnox-kernel-amd64-1.0.efi \ -append "root=/dev/sda" \ -device ich9-ahci,id=ahci -drive id=disk,file=moxnox-amd64-1.0.img,if=none \ -device ide-hd,drive=disk,bus=ahci.0 \ -nic user,model=virtio-net-pci \ -device qemu-xhci \ -device usb-kbd,id=kbd \ -device usb-tablet,id=tablet \ -serial stdio
如果你打算尝试自举之类的高负载操作, 就需要将内存从 1024 MB 调高。
对于 ARM,类似下面的命令应该可以运行:
qemu-system-aarch64 -M virt -cpu cortex-a76 -m 1024 \ -smp cores=4,threads=1 \ -kernel moxnox-kernel-aarch64-1.0.efi \ -append "root=/dev/sda" \ -device ich9-ahci,id=ahci -drive id=disk,file=moxnox-aarch64-1.0.img,if=none \ -device ide-hd,drive=disk,bus=ahci.0 \ -nic user,model=virtio-net-pci \ -drive if=pflash,unit=0,file=/usr/share/qemu/edk2-aarch64-code.fd,readonly=on \ -device qemu-xhci \ -device usb-kbd,id=kbd \ -device usb-tablet,id=tablet \ -serial stdio
安装
首先,使用 gparted 或类似工具创建一个新分区。32 GB 应该
绰绰有余。下面我将它称为 /dev/nvme0n1p99——千万别弄错。
请确保使用较新版本的 btrfs-progs,因为我们不支持旧版本使用的 某些默认设置。
准备根分区: ``
mkfs.btrfs /dev/nvme0n1p99
mkdir /mnt/moxnox
mount /dev/nvme0n1p99 /mnt/moxnox
cd /mnt/moxnox
wget https://github.com/maharmstone/moxnox/releases/download/v1.0/moxnox-amd64-1.0.tar.gz
tar -xvzf moxnox-amd64-1.0.tar.gz
rm moxnox-amd64-1.0.tar.gz
cd
umount /mnt/moxnox
``
复制内核: ``
mount /boot/efi
cd /boot/efi
wget https://github.com/maharmstone/moxnox/releases/download/v1.0/moxnox-kernel-amd64-1.0.efi
``
要安装启动项,可以执行类似下面的命令: ``
efibootmgr -c -d /dev/nvme0n1 -p 1 -L “Moxnox” -l ‘\moxnox-kernel-amd64-1.0.efi’ -u ‘root=/dev/nvme0n1p99’
``
efibootmgr 总喜欢在操作后更改启动顺序,这可能并不是
你想要的。块设备在 Linux 和 Moxnox 上的名称应该
基本相同。
这个“EFI”文件实际上是一个同时符合 Linux 启动协议的多格式文件, 所以它应该也能通过非 EFI 的 GRUB 启动。我没有测试过。 如何配置就留给读者自行探索了。
硬件支持
对于 amd64,所有内容都以 x86-64-v3 为目标编译,基本涵盖了
2015 年前后以来制造的所有设备。如果检测到 AVX512,Moxnox 会自动启用
并使用它。对于 qemu,你需要指定 q35 机器类型;
默认的 pc 机器太古老了,不支持 PCI Express。microvm
也可以使用。
对于 aarch64,我们使用 LSE 原子操作,它要求 ARMv8.1。这意味着
支持 Raspberry Pi 5,但不支持任何更早的型号。Moxnox 只支持 ACPI,不支持
设备树,所以在树莓派上还需要 https://github.com/worproject/rpi5-uefi。
遗憾的是,qemu 中没有 raspi5 机器类型,不过我已经成功使用
virt 运行,sbsa-ref 也可以。
设备支持:
- 块设备:NVMe、SATA、SDHCI(即 SD 卡)、virtio-block、USB 大容量 存储设备
- 网卡:virtio-net、RTL8168、RTL8125
- 输入设备:USB HID、PS/2 键盘、PS/2 鼠标、virtio-input
- 图形:virtio-gpu、GOP 帧缓冲、VBE、VGA 文本控制台(非 UEFI 启动时
传入
text=80x25) - 串口:virtio-console、x86 串口、PL011 ARM 串口
- USB:XHCI
构建
最简单的构建方法是拉取 Docker 容器 maharmstone/moxnox-ci-amd64
或 maharmstone/moxnox-ci-aarch64,其中包含面向
x86_64-pc-moxnox 或 aarch64-pc-moxnox 的交叉编译器。
然后在容器中执行:
$ git clone https://github.com/maharmstone/moxnox $ cd moxnox
CMake 会编译所有已检出的子模块。对于最小
系统:
$ git submodule update --init --depth 1 ports/acpica/repo ports/freetype/repo ports/gnu-efi/repo ports/harfbuzz/repo ports/libpng/repo ports/mingw-w64/repo ports/zlib/repo ports/musl/repo ports/tre/repo
要构建所有移植软件,请执行以下命令,这可能需要一些时间:
$ git submodule update --init --recursive
然后执行:
$ mkdir build $ cd build $ cmake -DCMAKE_TOOLCHAIN_FILE=amd64.cmake -GNinja ..
或者
$ cmake -DCMAKE_TOOLCHAIN_FILE=clang-aarch64-native.cmake -GNinja ..
请务必指定 Ninja——因为我们使用了 C++ 模块,所以需要它。CMake 默认使用 Unix Makefiles,而这无法正常工作。
最后执行:
$ ninja
由于体积较大,gcc、llvm 和 rust 默认不会编译,除非明确指定。
hexyl 和 ripgrep 也需要明确指定,因为它们
依赖 rust。
在 Moxnox 上构建的方法与上面相同,但不需要工具链文件:cmake -GNinja ..。
gcc、rust、hexyl 和 ripgrep 目前还不能在 Moxnox 中编译,但
其他所有软件都可以(只要等得足够久)。你可能需要大量内存,以及更多的
耐心。如果 CMake 报出有关 rust-libc 的错误,请确保你没有
检出 Rust 子模块。
许可证
内核和第一方程序采用 GPL 许可证。第一方
DLL 采用 LGPL 许可证。modules 目录中的内容采用
MIT 许可证。
有关各个移植软件的具体许可证,请参阅相应的子模块。
移植软件
目前已移植:
- bash
- binutils
- bison
- bzip2
- cairo
- cmake
- coreutils
- curl
- diffutils
- expat
- file
- findutils
- flex
- freetype
- gawk
- gcc(仅 amd64)
- git
- gmp
- gperf
- grep
- gzip
- harfbuzz
- hexyl
- jsoncpp
- less
- libarchive
- libiconv
- libpng
- librhash
- libuv
- llvm
- m4
- make
- mako
- markupsafe
- mesa
- mpc
- mpfr
- nano
- ncurses
- netcat
- ninja
- openssh
- openssl
- patch
- perl
- pixman
- python
- pyyaml
- readline
- ripgrep
- rust
- sed
- tar
- vim
- wget
- xz
- zlib
- zstd
常见问题
还缺少什么?
很多——但这毕竟是 1.0 版本。具体来说:
- 图形用户界面
- 对不同时区的支持
- 对不同键盘布局的支持
- 区域设置和非 UTF-8 字符集
- 任何形式的安全机制
- 多用户和用户组
至于性能等方面的问题:
- 用户空间的堆分配器还有很大的提速空间(这是自举时的 瓶颈)
- TCP 速度很慢,因为我们没有协商 MSS,并且一直使用默认的 64KB 窗口
- 我们应该在内存紧张时提前回写
- 应该有一个 LRU 系统,用于从页缓存中丢弃干净页……
- ……而 dentry 缓存从不清理,导致 inode 在被删除之前一直保持打开状态,这又让问题更加严重
显然,还应该移植更多软件并支持更多硬件。
它与 NT 的兼容程度如何?
我们的约定是,系统调用和底层接口与 NT 保持一致, 但守护进程和内核本身的结构不必一致。这与 ReactOS 的目标不同,后者旨在精确复刻 Windows。
因此:
- 二进制文件使用 PE 格式,而非 ELF,并带有
.exe或.dll扩展名 - C++ 异常通过 SEH 实现
- POSIX 信号通过异步过程调用实现
- 所有不在内核中、但类似内核的工作都在
ntdll.dll中完成 - rcx、rdx、r8、r9 调用约定与 Windows 一致
- 它在 C 语言方面的古怪之处也与 Windows 一致:
sizeof(long) == sizeof(int32_t)、sizeof(wchar_t) == sizeof(char16_t)、sizeof(long double) == sizeof(double)。
NT 的内容非常多,但其中尚未实现、又比较有意思的部分 包括令牌、注册表和 I/O 完成端口。
NT 有一套复杂的系统,其中存在一个隐藏的虚拟文件系统
(除非使用 winobj,否则看不到),文件的真实路径以
其块设备名称为起点(所以 C:\Windows\System32 实际上可能是 \Device\HarddiskVolume1\Windows\System32)。
我没有复刻这些机制。路径采用 POSIX 风格:使用正斜杠而非
反斜杠,以 / 作为根文件系统,并通过目录进行挂载。与真正的
Windows 不同,NtCreateFile 会解析 . 和 ..,以便更好地配合 dentry 缓存。
我刻意没有照搬的其他内容包括各种形式的事务, 它们是特定时代的产物;还有可分页内核内存的概念, 它带来的问题比解决的问题更多。
它与 POSIX 的兼容程度如何?
我们已经实现了 POSIX 2024 中约 1,200 个函数里的 642 个。这涵盖了
实际使用中的绝大多数函数,gnulib 则弥补了其中的一些
不足。与 Windows 不同,这里有 fork。我使用了 musl 的数学
和加密函数、mingw 的 printf 和其他一些功能,
以及 tre 的正则表达式。
与 Windows 一样,POSIX 函数分布在 ucrtbase、iphlpapi 和 ws2_32 中,
而 Windows 未实现的功能则放在 mnposix 中。
我大量借鉴了 Linux 最出色的设计:dentry 缓存、大型 folio、 映射全部物理内存、evdev。
其他 POSIX 不足之处:
- AF_UNIX 只完成了一半。
socketpair可以工作,包括 SCM_RIGHTS(ssh会使用它),但常规的客户端—服务器代码无法工作 mkfifo会创建一个 inode,但对它的 I/O 没有按预期重定向到 缓冲区- APC(即信号)只有在线程从系统调用返回时才会送达。
所以,目前运行
while (true) { }的程序无法被终止。
如何启动 sshd?
目前还没有自动启动守护进程的机制,所以需要手动启动。
首先生成主机密钥: ``
ssh-keygen -A
``
目前还没有密码支持,因此需要添加一个 /root/.ssh/authorized_keys
文件才能连接。如果遇到问题,请再次检查 /root 是否
归 root 所有,否则 sshd 会忽略此文件。
然后使用完整路径启动 sshd: ``
/bin/sshd.exe
``
它能运行 Windows 程序吗?
不能。至少目前还不能。
我们有意不实现任何 Win32 DLL,除了
kernelbase 中 mingw 运行时需要的几个函数。未来的一项改进可以是
彻底移除这些函数,然后移植 Wine 的 Win32 DLL 实现。
Wine 的某些部分,比如 wineserver 和 ntdll,我们并不需要,
因为我们已经自行处理了它们的工作。
这项目有多潦草?
所有实质性代码都不是由 AI 编写的。
我用 AI 辅助完成移植中的机械性工作(例如将
autotools 转换为 CMake、将 ioctl 调用替换为 tcgetwinsize、将
C 结构体转换为 Rust),也用它编写了一些冒烟测试(例如
cairo-test、mesa-test)。
不过,Claude 真正出色的地方在于审查你自己的提交。你给它 一个哈希值,它就会在你出丑之前,指出你遗留下来的 低级内存泄漏或死锁。
为什么要做这个?
为了好玩。而且,真正弄懂某样东西如何工作的唯一方法, 就是亲手尝试写一个。
此外,NT 内核被低估得令人发指,而且几乎不为
业余爱好者所知。它拥有的一些功能,Linux 花了很多很多年才提出
自己的设计,例如 eventfd 和 pidfd。
Windows 总是在完全兼容 POSIX 这件事上退缩,实在令人遗憾。早期 它有一个半成品版本,后来又有了 WSL1,结果 还是放弃了。Nano Server 也是一个很酷的想法,却同样 被放弃了。所以,这就是我对心目中 Windows 应有模样的诠释。
相似文章
QSOE: 受QNX启发的双内核架构操作系统
QSOE项目v0.1发布,提供与QNX兼容的操作系统,包含两种微内核变体(自定义Skimmer内核和基于seL4的内核),共享用户空间,并支持SiFive Unmatched RISC-V硬件。
一个受QNX启发的、具有可选内核的操作系统
QSOE 0.1,一个受QNX启发、具有可选内核(Skimmer微内核或seL4)的操作系统已发布。它面向64位RISC-V硬件,采用Apache-2.0许可证。
浏览器标签中的Windows内核,第一部分:冷启动、快速启动与四兆字节
本文介绍了 nanokrnl(一个用 Rust 编写的 64 位 Windows 内核)和 nanox(一个 65KB 的 WebAssembly 模拟器),后者可直接在浏览器中以长模式启动该内核,仅需约四兆字节即可运行一个操作系统。
Redox本月更新 - 2026年5月 - Redox - 你的下一代操作系统
Redox OS,一个用Rust编写的类Unix微内核操作系统,分享了其2026年5月的更新,包括宣布夏季代码项目、实现EEVDF调度器,以及I/O事件和文件系统inode缓存的显著性能改进。
MONOLITH: 一个实验性的非Unix操作系统,适用于x86架构
MONOLITH 是一个实验性的非Unix操作系统,适用于x86架构,作为开源项目托管在 Codeberg 上。