跳转到内容

LOCUS 1980 — 让一群机器看起来像同一台机器

是什么

LOCUS 是 UCLA 在 1980 年前后造的一个分布式操作系统。它最有名的卖点叫网络透明(network transparency)——你写程序的时候,看不出某个文件、某个进程是在自己机器上还是在隔壁机器上。

日常类比:想象一栋三层办公楼,每层都有一个文件柜。LOCUS 让你抽屉一拉,看到的是”全公司所有文件”——你拿到一份合同时根本不知道它的纸是从一楼调上来的还是本来就在你这层。中间所有”派人去一楼取”的过程,对你完全隐藏。

代码层面你写:

int fd = open("/usr/share/data.txt", O_RDONLY);
read(fd, buf, 4096);

/usr/share/data.txt 可能在本机硬盘,也可能在网线另一头第三台机器上。你的进程一字不改,syscall 都是同一套。LOCUS 在内核里偷偷把请求转发到对应节点。

LOCUS 还有两个同样大的卖点:进程能从一台机器迁到另一台网络断成两半时两边都还能继续工作

为什么重要

不理解 LOCUS,下面这些事都没坐标系:

  • 为什么 NFS(1985)一上来就敢说”远程文件系统调用和本地一样”——因为 LOCUS 5 年前就证明这条路能走
  • 为什么 Plan 9(1992)能说”一切皆文件,跨机器也是”——它就是把 LOCUS 的思想推到极致
  • 为什么 Kubernetes 能”把 pod 从一台节点迁到另一台还活着”——进程迁移这个概念 1980 年就在 LOCUS 里跑过
  • 为什么 nfs-1985 教科书里会一句话提到”网络透明的早期实践来自 LOCUS”——它是这一族的精神祖辈

核心要点

LOCUS 的设计可以拆成 三件大事

1. 网络透明的文件系统

每个文件有一个全局名字,比如 /usr/share/data.txt。这个名字不带”在哪台机器”的信息——内核自己根据一张目录表查它现在在哪。

实现上,LOCUS 把 Unix 的 inode 概念扩展成跨网络版本。本机打开文件时,内核发现”这个 inode 在节点 N3”,就把 read 请求打包成网络消息发过去;返回结果再当成本地数据塞回来。整个过程对用户进程完全隐藏。

类比:本地 inode 像本店仓库的货架号;LOCUS 的 inode 像快递单号——前缀写明哪个仓库,但你只看到一个统一的编号。

2. 文件可以多副本,但写起来像单副本

一份文件可以同时存在 N3、N5、N7 三台机器上。LOCUS 选其中一台当当前同步站点(current synchronization site, CSS),所有写都走它。CSS 用一个叫**影子页(shadow paging)**的技巧——

  • 写操作先在影子副本上做
  • 等用户 close() 文件时,原子地把影子换成正式版
  • 中途崩溃就丢掉影子,正式版没变

这就保证:“写到一半断电”不会留下半残文件。今天数据库的 copy-on-write、文件系统的 atomic rename,思路都是这个。

3. 网络断了也能继续干活

LOCUS 假设网络断。当一群机器分裂成两半(partition),两边各自选一个新的 CSS 继续读写。

合并时怎么办?LOCUS 检测每份文件被改的版本号——

  • 一边改了,另一边没改 → 直接采用改过的那份
  • 两边都改了 → 报冲突,让管理员或应用层来解(类似今天 Git 的 merge conflict)

这是 1980 年就在跑的最终一致性 + 冲突解决,比 Dynamo 论文(2007)早了将近 30 年。

实践案例

案例 1:进程迁移

LOCUS 允许一个正在运行的进程从节点 A 搬到节点 B,搬完继续跑。机制大致:

  1. A 把进程的内存页、寄存器、打开的文件描述符打包
  2. 通过网络发到 B
  3. B 在自己的内核里”复活”这个进程
  4. 它的 PID、对外通信的 socket 都不变

类比:你打游戏存档传到朋友机器上,他打开就接着你的进度玩——对游戏来说什么都没发生。

后来 Sprite / Mosix / 今天的 CRIU / Kubernetes pod 重调度,都是这条路上的孩子。

案例 2:跨节点 fork

更狠的:LOCUS 允许 fork() 出来的子进程跑在另一台节点上。

pid_t pid = fork();
if (pid == 0) {
// 子进程可能在节点 5 上跑,但代码什么都不用改
execve("/usr/bin/heavy_compute", ...);
}

调度器看哪台节点闲就把子进程派过去。父子之间的管道、共享文件描述符一样工作——只是变量在两台机器的内存里。

案例 3:异构 CPU 也能跑

后期版本 LOCUS 支持同一文件系统里同时挂 VAX、PC、IBM 大型机。文件系统记录”这个二进制是给哪种 CPU 的”,exec 时自动选本机能跑的版本。这个能力后来叫 TCF(Transparent Computing Facility),被 IBM AIX/370 商用化。

踩过的坑

  1. 网络透明的代价是可观测性丢失:你 open() 一个文件用了 100ms 还是 1ms 完全看不出来——可能本地命中也可能跨网。性能问题极难调试。后来人们意识到,完全透明反而坏:开发者需要知道 “这个调用要走网络”。NFS 之后的系统普遍保留了 mount point 这种半透明设计。

  2. 副本一致性的复杂度爆炸:CSS 选举、影子页提交、partition 合并——每一条路径都有边角情况。论文里花大量篇幅讲”如果 CSS 在提交中途崩溃怎么办”——这是后来 Paxos / Raft 想统一解决的问题。

  3. 难扩展到 30 节点以上:所有节点要互相知道彼此存在、维护一致的目录视图。规模上去后元数据同步成瓶颈。后来的 afs-1988 / coda-1990 改用层级缓存 + 回调失效绕开这个限制。

  4. 进程迁移的”开放文件”地狱:迁过去后,原节点上还开着的文件、socket、设备怎么办?LOCUS 用大量胶水代码处理,但很多组合根本无解。今天 CRIU 仍在和这个问题搏斗——一个 GPU 句柄基本没法迁。

适用 vs 不适用场景

适用

  • 同构小集群(10~20 台同型号 Unix 机器),强协作,弱地理分布
  • 需要”用户感觉是一台大机器”的场景——研究所、设计工作站群
  • 副本数固定、改动频率低、大多数操作是读

不适用

  • 大规模数据中心(上千节点)→ 用 afs-1988 / Ceph 等
  • 异地 / WAN → 网络透明假设不成立,得显式 RPC
  • 性能极敏感场景 → 透明性掩盖了延迟,没法精细优化
  • 需要不可信节点 → LOCUS 假设所有节点互相信任,没设计认证

历史小故事(可跳过)

  • 1979 年:Gerald Popek 在 UCLA 启动 LOCUS 项目,目标是把校园里几十台 VAX/PDP 串成”一台大机器”
  • 1981 年:SOSP-8 发表 LOCUS 论文,网络透明 成为分布式系统词典里的标准术语
  • 1983 年:Locus Computing Corporation 成立,把它商业化
  • 1988~1995 年:IBM 把 LOCUS 思路集成进 AIX/370 和 OSF/1 AD(DEC Alpha 集群操作系统)
  • 2000 年代:Locus Computing 被 Platform Computing 收购,Platform 后来又被 IBM 收购

LOCUS 没有像 Unix 那样席卷世界,但它定义的几个词——网络透明、进程迁移、partition tolerance——成了之后所有分布式 OS 论文的共同词汇。

学到什么

  1. 透明不是免费的:把”远程”完全藏起来好用,但当性能或失败模式不一样时反而误导人。后来 NFS 选择部分透明,是吸取了 LOCUS 的教训
  2. 副本 + 原子提交这套思路在 1980 年就基本完整了——CSS、影子页、版本号冲突。后来分布式数据库只是把它们堆得更大、证得更严
  3. 进程迁移是正交于文件系统的能力——LOCUS 把两件事一起证了,但今天大多数系统只挑其一(K8s 几乎不迁运行中进程,只重启)
  4. 理论 → 系统 → 工业:UCLA 论文 → Locus 公司 → IBM AIX → 思路扩散到 NFS / Plan 9 / Sprite,每一跳花 5~10 年

延伸阅读

  • 论文 PDF(ACM):Walker et al. 1983 — The LOCUS Distributed Operating System(SOSP-8 原文,14 页)
  • 后续综述:Popek & Walker, The LOCUS Distributed System Architecture(MIT Press 1985,整本书)
  • nfs-1985 —— 4 年后 Sun 借用网络透明思想做的协议,但选择了无状态服务器
  • afs-1988 —— CMU 的另一条路:客户端缓存 + 回调失效,绕开 LOCUS 的扩展瓶颈
  • coda-1990 —— AFS 后继,把 LOCUS 的”分区也能继续工作”重做了一遍

关联

  • nfs-1985 —— 直接受影响:网络透明这个词从 LOCUS 进入 NFS 设计文档
  • afs-1988 —— 同时代竞品;选了不同的扩展路线
  • coda-1990 —— 把 LOCUS 的 disconnected operation 思想工程化
  • unix-1974 —— LOCUS 是 Unix 的分布式扩展,所有系统调用语义都来自这里
  • paxos-1998 —— 解决了 LOCUS 里手写的 CSS 选举问题,给出统一证明

反向链接

  • afs-1988 —— AFS 1988 — 客户端缓存 + 回调失效让分布式文件系统真正能扩展
  • coda-1990 —— Coda 1990 — 笔记本拔网线照样写文件,重连后自动合并
  • nfs-1985 —— NFS 1985 — 让远程磁盘看起来像本地磁盘
  • paxos-1998 —— Paxos 1998 — 古希腊议会寓言里藏的共识协议