Plan 9 — 把"一切皆文件"真的做到极致的下一代 UNIX
是什么
Plan 9 是 1990 年代 Bell Labs(写出 UNIX 的同一拨人:Pike / Thompson / Ritchie)做的下一代 UNIX。一句话:他们觉得 UNIX 当年说的”一切皆文件”其实没说话算数,于是重写一遍,这次真的让一切都是文件。
日常类比:UNIX 像 1970 年代承诺”全屋一个开关控制所有电器”的智能家居,结果 30 年后冰箱有自己的 app、空调有自己的遥控、灯泡有自己的协议。Plan 9 是 1995 年回头说:“好吧,我们重做。这次冰箱、空调、灯泡、邻居家的电视、楼下的咖啡机,真的全都用同一个开关。”
那个”统一开关”叫 9P 协议——13 种消息(open / read / write / walk / create…),任何东西想被使用,就开一个 9P 服务,把自己暴露成文件树。本地硬盘、远程进程、声卡、显示器、网卡、CPU 算力——全部是文件。
为什么重要
1995 年的 Plan 9 工业上失败了——但你今天用的几乎所有”现代基建”都在偷它:
- Docker / 容器:每进程独立命名空间(per-process namespace)是 Plan 9 1992 就有的;Linux 2002 起抄进 mainline,2013 年被 Docker 包装一下成了云原生
- WSL:早期 WSL 用 9P 做 Windows 和 Linux 子系统的文件共享,直接复用 Plan 9 协议
- Linux v9fs:内核里就有 9P 客户端(2005 年进主线),KVM 的 virtio-9p 让虚拟机和宿主共享文件
- Go 语言:Pike / Thompson 两位 Plan 9 作者后来到 Google 做 Go;Go 的并发原语、汇编语法、runtime 风格全是 Plan 9 血统
- FUSE(用户态文件系统):思想直接来自 Plan 9——任何程序都能当文件服务器
不读 Plan 9,看到 Docker、WSL、Go 都觉得是”现代发明”;读了之后发现这些核心点子 30 年前就完整存在。
核心要点
1. 9P 协议:万物的统一接口
UNIX 说”一切皆文件”,但实际上:网络是 socket(独立 API)、显示是 X11(独立协议)、进程间通信是 pipe / shm / msgq(一堆独立 API)。
Plan 9 把这些全部改成文件树:
- 网络栈:
/net/tcp/0/data写入就是发 TCP 包,/net/tcp/0/localcat 出来是本地地址 - 进程:
/proc/<pid>/mem是该进程内存,echo kill > /proc/<pid>/ctl杀进程 - 窗口:
/dev/mouse读出鼠标事件,/dev/cons写入显示在窗口
任何资源只要实现 9P 协议就能加进来。9P 在网络上传输——所以远程文件和本地文件没区别。
2. Per-process namespace:每个进程一棵自己的树
UNIX 全系统共享一棵 /。Plan 9 让每个进程有自己的文件树视图:
$ bind /n/remote/bin /bin # 把远程目录叠到本地 /bin$ mount tcp!server!9fs /n/share # 挂个远程 9P 服务这些操作只影响当前进程及子进程,不动别人。这就是后来 Linux mount namespace(Docker 容器隔离的底层)的源头——只是 Plan 9 是默认每个进程都用,没有 “需要 root” 这一说。
3. 三类机器靠 9P 缝在一起
90 年代工作站时代:终端轻量带屏幕、CPU 服务器算力强、文件服务器存数据。Plan 9 让这三类机器通过 9P 拼成一个虚拟系统:
- 用户在终端登录,命名空间挂载文件服务器的
/usr - 想跑大计算?把 CPU 服务器的
/procmount 进来,进程在远端跑,I/O 走 9P 回到终端 - “跨机器开进程” 不是分布式 API,是命名空间编排
实践案例
案例 1:用 cat 跟远程进程”说话”
Plan 9 里跑一个进程,pid=42。你想看它内存?
$ cat /proc/42/mem | xxd | less想杀它?
$ echo kill > /proc/42/ctl想 attach 调试?
$ acid 42 # acid 内部就是读 /proc/42/regs /proc/42/memLinux 的 /proc 抄了一半(只读信息),但写控制那部分没敢抄——Plan 9 真敢让 echo 杀进程。
案例 2:bind 一行做出 chroot+overlayfs
Plan 9 的 bind 比 UNIX 强大:
$ bind -a /n/remote/bin /bin # /bin 现在是本地+远程的合并$ bind -b /tmp/override /etc # /etc 优先看 /tmp/override,找不到才看原 /etc这就是 union directory——两个目录叠成一个,read 时合并显示。Linux 2014 才用 overlayfs 做出来,Plan 9 1992 就有,而且不用 root。
案例 3:9P 在今天的 WSL 里还活着
WSL 1 早期把 Windows 文件系统暴露给 Linux 子系统,用的就是 9P 协议——\\wsl$\Ubuntu\home 这种路径背后就是个 9P 服务器。微软直接拿 Plan 9 的协议来用,不用重新发明。
踩过的坑(Plan 9 自己的)
- 拒绝 POSIX 兼容:跑不了 GCC / Emacs / X11,应用池太小,开发者不来——这是工业上失败的最大原因
- 9P 在广域网慢:walk 一段路径要逐段 9P 往返,跨地理距离体验差。后来 9P2000.u 增加批量操作缓解
- CPU 服务器模型超前但过时:90 年代后期 PC 算力涨得太快,“借远程 CPU”成了伪需求;要等 2010 年代云计算才真正回来
- GUI 反主流:Acme / Rio 极简到没有标题栏没有右键菜单,新人完全不会用
- 没有发行版生态:Bell Labs 内部 + 几个大学研究者自用,从没像 Linux 那样有 Debian/RedHat 这种推广者
适用 vs 不适用场景
思想适用(今天还在用):
- 容器隔离(每进程命名空间)→ Docker、LXC、systemd-nspawn
- 虚拟机共享文件(9P)→ KVM virtio-9p、WSL、QEMU
- 用户态文件系统(FUSE 思想源头)→ sshfs、s3fs、各种”把 X 暴露成文件”
- 把”分布式”退化成”命名空间编排”→ Kubernetes 部分思想(Pod 共享 namespace)
直接用 Plan 9 不适用:
- 跑现代应用栈(Chrome / VSCode / Docker 本身)→ 9front 也跑不动
- 大规模生产环境 → 没有商业支持,2026 年只剩社区 fork(9front)
- 团队协作开发 → 工具链(git/IDE)支持极弱
历史小故事(可跳过)
- 1985-1989:Bell Labs 内部 UNIX 已演进到 v8/v9/v10,但 Pike / Thompson 觉得修不动了,开始想”如果重做会怎样”
- 1992:Plan 9 第一次外发,给少数大学研究者
- 1995:本论文发表在 Computing Systems 期刊(Bell Labs 内部刊物文化,没投 SOSP)
- 1995-1996:衍生出 Inferno(小型嵌入式版本,带 Limbo 语言——后来 Limbo 的 channel 直接变成 Go 的 channel)
- 2000s:商业上死了。Pike / Thompson 进 Google
- 2007-2009:Pike / Thompson / Griesemer 在 Google 做 Go——Go 的 runtime 用 Plan 9 汇编语法写的,goroutine + channel 是 Plan 9 libthread/Limbo 的直接继承
- 2014-至今:9front 社区 fork 活跃维护,Plan 9 思想在容器、WSL、Go、FUSE 里持续生根
名字 “Plan 9” 来自 1959 年 B 级科幻片《Plan 9 from Outer Space》,号称”史上最烂电影”——Bell Labs 故意选这个反叛 UNIX 的严肃感。
学到什么
- 失败的产品 + 成功的思想:Plan 9 工业上彻底失败,但它的核心点子(namespace / 9P / 一切皆文件极致化)30 年后塞满你每天用的 Docker / WSL / Go
- 正交性 > 功能堆:UNIX 30 年累积出 socket/ioctl/sysfs/X11 一堆独立 API;Plan 9 用一个 9P 全包了。少而强 > 多而专
- 重做的勇气:UNIX 原班人马敢说”我们当年没做对,再来一次”。这种自我否定在工业界极少见
- 思想会迁徙:Plan 9 死了,思想搬进 Linux namespaces;Linux namespaces 死板,思想搬进 Docker;Docker 太重,思想搬进 WASM。好点子永远在找新宿主
延伸阅读
- 论文 PDF:Plan 9 from Bell Labs(30 页,1995 年原文)
- 9front 项目:活跃维护的 Plan 9 社区 fork,可以装在 VM 里实际玩
- Linux v9fs 文档:9P 在今天 Linux 内核里的样子
- mccarthy-lisp —— 同样是”少而强的原语”哲学的祖先
- unix-time-sharing —— Plan 9 的前身,“一切皆文件”思想的原始版本
关联
- unix-time-sharing —— Plan 9 是 UNIX 的第二次尝试,对比看”原版承诺 vs 极致兑现”
- mccarthy-lisp —— 共享”少量正交原语”哲学
- lambda-calculus —— Pike 后来做 Go 时把 Plan 9 思想 + 函数式血统揉在一起