进程拿到整个低半区,Go 默认编译的程序和 Debian 的 python3 在 RustROS 容器里照常运行。内核同时加上了常规的内存保护。按用户确认的设计(docs/user-address-space-design.md)完成,四项决定都按建议。
以前内核用"虚拟地址 = 物理地址"的映射占着低 64 TiB,进程只能从 64 TiB 起放东西。按固定地址链接的程序(Go 默认编译、Debian 的 python3)要装在 0x400000,正好落在内核那块里,所以装不进去。python3 自己的安装脚本也要调用 python3,所以 apt-get install python3 本身就失败。
| 范围 | 用途 |
|---|---|
| 0x10000 – 0x7FFF_FFFF_F000 | 进程自己的(低半区整个) |
| 0xFFFF_8000_0000_0000 | 线性映射:全部内存,不可执行 |
| 0xFFFF_C000_0000_0000 | 设备寄存器,按需映射,不缓存 |
| 0xFFFF_D000_0000_0000 | 模块,按页映射:代码只读、数据不可执行 |
| 0xFFFF_FFFF_8000_0000 | 内核本身:代码只读,其余不可执行 |
所有常量都在 crates/api/src/layout.rs 一处。系统调用的开销和以前一样:内核的高半区在每个地址空间里都有,不切页表。
Hw::dma_alloc / Hw::dma_map;map_device 返回寄存器的地址。以后有 IOMMU 时驱动不用改。aslr=off 关掉(命令行或启动状态)。uefi.rs 没改。PE stub 调用它时给它一份页表,里面有固件自己的映射,加上高半区的内核。| 检查 | Debian 13(debian_test) | LXC Debian 13 cloud,路由容器(node_test) |
|---|---|---|
| Go 默认编译,静态(8 个 goroutine、定时器、64 MiB、GC) | 通过 | 通过 |
| Go 默认编译,cgo(glibc 的 ld.so) | 通过 | 通过 |
apt-get install -y python3 | 通过 | 通过 |
python3 -c 'import ssl, json, sqlite3' | 通过 | 通过 |
pip --version(python3-pip,不装推荐包) | pip 25.1.1 | 通过 |
新的 lowaddr 测试程序(proc_test)是真正装在 0x400000 的固定地址程序,13 项检查全部通过:MAP_FIXED 映射 0x10000 和 0xc000000000、地址提示按原样给、0x10000 以下映射不了;读原恒等映射的地址、内核本身、线性映射、vsyscall 页都会被 SIGSEGV 终止;两次运行的栈和 mmap 地址不同。
#! /bin/sh -e(#! 后面有空格):以前把 "/bin/sh -e" 整个当成程序名,dpkg 执行 readline-common 的安装脚本时报 ENOENT。现在和 Linux 一样处理(linux 模块)。services.rs)。还有的已知问题(不是这次引入的):私有文件映射是整个复制进内存的。apt 会映射约 80 MB 的包缓存,所以在只有 256 MiB 内存的测试机里 fork 会失败("Failed to fork")。Debian 测试机现在给 1 GiB,客户容器的内存比这大得多。以后可以改成从页缓存按需读入。
rustros-update.py deploy 会处理)。