跳转到内容
← 返回先驱
软件工程先驱1936–12 分钟阅读

玛格丽特·汉密顿

Margaret Hamilton

1969 年 7 月 20 日,阿波罗 11 号登月舱距离月球表面还有约 3000 米时,飞行计算机突然发出警报——代码 1202。宇航员尼尔·阿姆斯特朗向地面报告,休斯顿控制中心紧张地评估:这个错误代码意味着什么?着陆是否应该中止? 程序员们知道这个代码意味着什么:飞行计算机的内存过载了,但系统按照预先设计的逻辑,主…

软件工程阿波罗计划容错系统NASA

1969 年 7 月 20 日,阿波罗 11 号登月舱距离月球表面还有约 3000 米时,飞行计算机突然发出警报——代码 1202。宇航员尼尔·阿姆斯特朗向地面报告,休斯顿控制中心紧张地评估:这个错误代码意味着什么?着陆是否应该中止?

程序员们知道这个代码意味着什么:飞行计算机的内存过载了,但系统按照预先设计的逻辑,主动抛弃了低优先级任务,确保最关键的着陆任务得以继续运行。这个行为不是意外,而是预先编写的容错设计。系统在压力下正确地降级运行,登月继续。

这套软件背后的架构师,是玛格丽特·汉密顿(Margaret Hamilton)。

破除误解:汉密顿不是"碰巧"参与了阿波罗

历史上存在一种叙述,暗示汉密顿(以及其他阿波罗项目的女性工程师)是因为战时人力短缺或者机缘巧合而参与了软件工作,并不代表真正的技术核心。这是严重的误解。

汉密顿不仅参与了阿波罗飞行软件的开发,她领导了 MIT 仪器实验室(MIT Instrumentation Laboratory,后改名 Draper Laboratory)的飞行软件工程部门,负责阿波罗引导计算机(Apollo Guidance Computer,AGC)上运行的所有板载软件。她是技术团队的负责人,不是执行者。

现场:没有"软件工程师"这个词的时代

汉密顿 1936 年 8 月 17 日生于印第安纳州帕奥利,1958 年在厄勒姆学院(Earlham College)获得数学学士学位(辅修哲学)。毕业后,她原本打算去密歇根大学读数学研究生,但需要先赚钱供丈夫读书,于是去了 MIT。

她最初加入的是气象学家爱德华·洛伦茨(Edward Lorenz)的团队——那个发现混沌理论"蝴蝶效应"的洛伦茨——为他的天气预测程序编写代码。那时没有软件工程这门学科,没有编程语言教材,没有"软件工程师"这个职业头衔。程序员们摸索着写代码,没有规范,没有方法论。

1961 年起,她在 MIT 林肯实验室工作了三年,参与 SAGE 半自动地面防空系统的软件——那是当时世界上最庞大的实时计算机系统,要全天候不间断地处理雷达数据。在那里她第一次认真思考一个问题:软件出了错而没人来得及纠正,会发生什么?1960 年代中期,她转入 MIT 仪器实验室,正赶上阿波罗计划软件开发的起步。

阿波罗软件的工程挑战

阿波罗引导计算机(AGC,Block II)是当时最复杂的嵌入式计算机系统之一,但按今天的标准极其有限:2048 字(约 2KB)的可读写磁芯内存,36864 字(约 72KB)的只读内存(程序存储在绕线磁芯存储器中,字面意义上是用针和线手工编制的),运行速度约 43000 条指令/秒。

在如此有限的资源上,必须运行覆盖整个任务剖面的飞行软件:发射、在轨飞行、月球轨道插入、登月舱分离、下降着陆、月面作业、上升返回、对接、地球返回。每一个阶段的代码都必须精确,任何错误都可能导致任务失败或宇航员死亡。

只读内存的制造方式最能说明那个时代的"软件"意味着什么。AGC 的程序存在磁芯绳存储器(core rope memory)里:导线穿过磁芯是 1,绕过磁芯是 0。这些存储模块由雷神公司(Raytheon)马萨诸塞州沃尔瑟姆工厂的女工在类似织机的工装上一针一线"织"出来——她们多是纺织业出身,工程师半开玩笑地称之为 LOL 存储器(Little Old Lady memory)。一个模块要织约八周,造价约 1.5 万美元(1960 年代币值)。这意味着软件必须在发射前几个月就彻底冻结:没有热修复,没有补丁,发出去是什么就是什么。在这样的介质上,"第一次就把事情做对"不是口号,是物理现实。

汉密顿的团队面对的核心挑战:软件如何在极端资源约束下可靠运行,并在任何意外情况下优雅降级而不崩溃?

核心贡献一:异步优先级系统

汉密顿设计了 AGC 软件中的优先级调度系统(priority scheduling):所有任务按重要性排队,当资源不足时,低优先级任务自动被挂起或中止,高优先级任务(如导航和着陆控制)始终能获得资源。

1202 报警正是这套系统的体现。登月当天,交会雷达的一个开关被留在了错误的位置,雷达持续向计算机发送并不需要的数据,吃掉了大量运算时间。计算机无法排下所有任务,于是触发 1202(执行溢出)警报,同时自动抛弃低优先级任务,优先保障导航、制导与发动机控制。整个下降过程中警报一共响了五次——四次 1202、一次 1201——每一次,计算机都执行一次"软重启":清掉可丢弃的任务,保住关键程序,然后接着下降。

真正惊险的决策在地面。制导官史蒂夫·贝尔斯(Steve Bales)只有几秒钟判断警报是否危及着陆。后台房间的年轻工程师杰克·加曼(Jack Garman)事先把所有报警代码手写成一张速查表贴在控制台上——他认出 1202 属于"只要不连续出现就可以继续"的那一类。贝尔斯据此喊出了"Go"。这个判断靠的不是运气,而是两套人事先的准备:汉密顿团队写进软件的降级逻辑,和加曼写在纸上的代码清单。

核心贡献二:"软件工程"这个词

汉密顿是最早将"软件工程"(software engineering)作为正式术语使用的人之一,并有意识地推动建立软件开发作为一门工程学科的基础。

在阿波罗项目的早期,"软件"被视为次要的、附属的工作——"真正"的工程是硬件。汉密顿积极主张:软件开发应该与硬件工程具有同等的严格性和系统性,应该有规范的开发方法、测试程序和文档标准。她倡导用"软件工程师"来称呼她团队的成员,以强调这项工作的工程属性。

这个坚持在今天看来理所当然,但在 1960 年代,它需要与整个工程文化对话,甚至抗争。

这个词的发明权本身也有一桩公案。汉密顿回忆,她在 MIT 提出"软件工程"时,是半开玩笑半认真地要为软件争取与其他工程学科同等的"合法性"(legitimacy)。1968 年北约在德国加米施召开的会议让这个词广为人知;而后来的文献考证发现,"software engineering"在印刷品中更早的出现可追溯到 1966 年的一则报纸广告。确切的首创者或许无从稽考,但把这个词从一个称呼变成一门学科的自我要求,汉密顿是最重要的推动者之一。

核心贡献三:自检系统哲学

汉密顿的另一个贡献是在系统设计中嵌入大量的自检代码(self-checking code):程序在运行时持续检查自身的状态,在发现异常时采取主动的恢复行动,而不是在崩溃后等待外部干预。

这个哲学在今天被称为防御性编程(defensive programming)和故障容忍(fault tolerance)。在 1960 年代没有硬盘备份、没有远程重启的太空任务里,这种设计哲学不是选项,而是生死攸关的必要条件。

离开 MIT 之后

1976 年,汉密顿离开 MIT,创立了 Higher Order Software(HOS),开发基于形式化规约(formal specification)的软件开发方法。1986 年她创立了 Hamilton Technologies,继续从事可靠性软件开发工具的研究。

她把阿波罗年代的方法论凝结为"防患于未然"(Development Before the Fact,DBTF)的哲学:与其写完再测试,不如用形式化定义让某类错误在定义层面就写不出来。以此为基础,她设计了通用系统语言(Universal Systems Language,USL)及配套的 001 工具套件,2008 年还在《IEEE Computer》上撰文回顾这条从阿波罗出发的路线。业界对 USL 的评价并不一致——它始终是小众工具——但它代表了她从阿波罗带走的核心信念:可靠性应当被设计进去,而不是测试出来。

她的获奖记录: - 1986 年:女性计算机协会奥古斯塔·艾达·拉芙蕾丝奖 - 2003 年:NASA 杰出太空行动奖(有史以来 NASA 颁发金额最高的此类奖项) - 2016 年:总统自由勋章(Presidential Medal of Freedom),由奥巴马总统颁发,是美国最高平民荣誉

代价与争议

一张著名的照片流传甚广:汉密顿站在一叠高及她肩膀的打印纸旁边微笑——那叠纸是阿波罗导引软件的源代码打印件,高度将近与她齐平。这张照片成为了计算机科学和女性工程师力量的符号。

但历史公正要求指出:阿波罗软件是数百名工程师和程序员的集体成果。汉密顿是领导者和关键架构师,但把所有功劳归于她一人同样是对其他贡献者的不公平。她自己在多次访谈中强调了这一点。

跨域连接

  • 机会成本:优先级调度的实质,是承认资源不足时必然有任务被牺牲,并事先决定牺牲谁。不做这个决定并不等于不牺牲,只是把选择权交给了随机的过载顺序。推论可以直接观察:没有显式优先级的系统在过载时表现为全体劣化,而不是关键功能被保全——登月那次告警之所以不是事故,差别就在这里。
  • 控制论:自检与恢复构成一个闭环——系统持续测量自身状态与合法状态的偏差,并在越限时施加纠正;开环设计假设不会出错,因而在扰动面前没有任何余量。闭环的前置条件也由此确定:必须先能观测自己。可观测性于是不是可靠性的附属品,而是它的前提。
  • 循证医学:一项工作从手艺变成学科的标志,是它开始要求"你凭什么说这样更好"的证据,并把方法写成他人可复核的程序。她坚持软件应与硬件受同等约束,走的正是这一步,遇到的阻力也与循证转向如出一辙:经验权威不愿被可复核的程序取代。
  • 工艺安全:重大事故极少由单一失效造成,而是多个各自可容忍的偏差同时对齐。一个飞行前设置导致雷达持续占用算力,本身并不致命,致命的是它与着陆时的峰值负载重合。防护因此必须分层且互相独立——最内层的调度不依赖外层配置是否正确,若各层共享同一假设,层数再多也只等于一层。
  • 实时系统:那次告警说明系统在过载时不是崩溃而是有序降级,前提是每个任务都事先声明了优先级与截止时间。实时性的定义因此不是"快",而是"最坏情况下关键任务仍能按时完成"——平均延迟再低,只要最坏情况无界,就不能用在这种场合。

参考文献

  • Hamilton, M. H. Computer Got Loaded. Datamation, 1 March (1971). (汉密顿致 Datamation 编辑的信,澄清阿波罗 1201/1202 警报事件的真实性质)
  • Murray, C. & Cox, C. B. Apollo: The Race to the Moon. Simon & Schuster (1989). (阿波罗计划的工程史,软件部分有详细叙述)
  • Mindell, D. A. Digital Apollo: Human and Machine in Spaceflight. MIT Press (2008). (学术角度分析人机交互在阿波罗中的作用)
  • Hamilton, M. & Hackler, W. R. Universal Systems Language: Lessons Learned from Apollo. IEEE Computer 41(12), 2008. (汉密顿本人对阿波罗软件工程经验的回顾)