软件控制等级军事标准
想到的包括锤击效应、宇宙级位翻转、硬件故障或编译器漏洞。
MIL-STD-882E标准规定了软件控制等级,即根据软件所承担的职责划分其潜在危险程度。尽管该标准较为复杂,但可简化为四个核心等级:
- 最危险的情况是软件直接控制某项功能,若软件操作失误将立即引发危险。
- 次高危险等级包括:(a) 软件虽直接控制系统,但错误操作与实际危险之间存在延迟;或 (b) 软件不直接控制系统,但操作人员必须立即响应软件信号采取行动以防危险。例如:反应堆爆炸前仅剩数秒时,软件发出停堆指令。
- 风险更低的情况是软件不直接控制系统,且有时间通过独立方法验证其建议,确保软件推荐的操作确实合理。
- 最安全的情况是软件仅作为辅助工具使用,不参与关键系统的控制。
我认为这种分类方式颇具洞见,尤其在机器学习与计算机视觉技术正为软件注入新机遇的当下——这些技术正将软件从从属人类的状态,推向深度参与人类决策流程的新领域。
本文文字及图片出自 Military Standard on Software Control Levels,由 WebHek 分享。

许多人试图通过模仿安全关键开发标准中的流程环节来提升质量。实际上,90%的质量收益源于静下心来思考软件及其在整体系统中的作用。你无需依赖那些花哨的方法论和昂贵的工具——这恰恰是形式化方法的核心价值所在。
我发现,以“必须全面理解所开发对象”为起点质量流程,对尚未接触这些方法的人而言几乎毫无可行性。完整梳理代码与外部世界的所有交互方式极其困难。即便少数工程师能完成这项工作,他们也鲜少被赋予决策权——既无法判断故障后果是否可接受,更无权在不可接受时实施修复。
更糟的是,许多流行方法论完全聚焦于故障场景。它们不断追问“该部件故障概率多高?”“故障会引发什么后果?”“如何降低故障风险?”等等。但软件从不会真正“故障”[1],这种出发点本身就是错误的!
更合理的方式如你所言:思考软件在系统中的角色定位。实现路径可正式可非正式,但绝对优于组件视角。
关键在于,所谓故障并非指部件未能完成客观定义的功能,而是未能达到我们预期的运行状态。换言之,故障的根源在于我们自身。归纳而言,若`x`发生故障,则意味着要么我们未能正确定义`x`,要么模拟`x`的`y`(编译器等)已发生故障。
当然,“故障”概念本身就预设了目的性。这是规范性概念,而没有目标就谈不上规范性。
因此,对于人类创造的产物,我们不能单纯谈论某个部件的失败。因为与自然物种(如人类自身,其规范性内在于个体,故心脏衰竭是客观失败)不同,人工制品的“应当”或“理应”状态完全取决于外部人类的意图与预期。
而“系统中的角色”本质上正是目的论视角的体现。系统拥有整体目的(由我们赋予),任何部分的角色或功能皆以服务于该目标为定义。若系统运行路径为`a->d`,某部件路径为`a->b`,另一部件`b->c`,再另一部件`c->d`,则这些路径的组合构成了系统。部分的意义源于整体的意义。
包含软件的系统会发生故障,且故障根源可能源于软件本身。
而你试图引用的文章存在根本性谬误。例如Therac-25医疗设备的设计初衷并非在操作员快速输入时输出高功率——而是其结构本身导致了这种结果。这好比将飞机失事归咎于螺栓强度不足:“螺栓并未失效;它完全按照尺寸预期的力值断裂;若想避免断裂,就该用更大规格的螺栓!”正如Therac案例所示,此类故障具有高度可复现性。
我们的主要分歧似乎在于是否将其称为“设计错误”或“制造错误”,但我认为这并不能抹杀“产品初始即存在的缺陷”与“组件突然失效导致功能异常”之间的实质区别。
我认为这确实是部分原因。我同时认为,当物理组件承受其无法承受的应力时——即使这些应力在设计阶段被认定属于预期环境范围(例如强度不足以应对预期工况的螺栓)——这种情况同时符合:
1. 通常被称为部件“故障”
2. 与导致系统崩溃的许多软件缺陷高度相似
> 通常被称为
当然,人们可能草率地称之为故障,但这样就忽略了有助于构建更健壮软件的关键区别。
螺栓设计不足以满足预期用途属于设计错误。当它断裂时,这是设计可预见的(但不幸的)运行模式,而非故障。(它无意中被设计成易碎连接件。)
区分这两种情况至关重要,因为我们需要采取不同的应对策略。
你提及了需求与约束的区别。你的观点没错,但同样正确的是:Therac-25的设计初衷并非防止操作员快速输入时输出高功率。
提醒一下:你添加了[1]标记,却忘了附上引用的链接!
可能是这样:
原因在于,在软件之外的其他领域,人们必须应对物质的顽固性。当你设计电路、汽车或化学品时,必须面对这样一个事实:这些物理物质只会按其本性行事,而非按预期行事。而我们软件领域没有这个问题,这使得工作变得极其轻松。我们设计的是一组理想化的数学组件,它们有明确定义,只会精确执行被赋予的功能。
因此程序员无需面对诸多难题。例如将’if’语句嵌套在’while’循环中时,我们不必担心’if’语句能否获得足够能量以正常运行速度执行。不必担心运行速度会产生射频干扰,导致数据其他部分出现错误值。不必担心循环速度引发共振,最终使’if’语句与’while’语句相互振动,导致其中一个部件断裂。我们不必担心环境中的化学物质渗入if语句与while语句的边界导致腐蚀,造成接触不良。不必担心其他化学物质附着引发短路。不必担忧热量能否通过周围的while语句从if语句中散发出去。不必担忧’while’语句是否会造成电压骤降导致’if’语句失效。查阅变量值时,无需顾虑引用次数是否超出扇出限制。不必担忧某个变量内存在多少电容,也不必计算存储数值所需的时间。
所有这些要素都以特定方式被定义,系统被设定为按特定方式运行,且始终如此。实体计算机可能发生故障,但这绝非程序的过错。正因无需处理这些问题,我们的领域变得无比轻松。"
——理查德·斯托曼,2001年:<https://www.gnu.org/philosophy/stallman-mec-india.html#conf9>
想到的包括锤击效应、宇宙级位翻转、硬件故障或编译器漏洞。
前三者属于硬件故障而非软件故障。后者应归为设计缺陷而非故障。
软件或许需要处理硬件故障,但不处理此类问题的软件也不算故障——只是设计不完善。
作为程序员,这些都不该成为你需要担心的问题。
反驳观点:我在设计备份脚本时绝对考虑过这些因素。正因如此,我会在传输前、传输后及定期间隔对文件进行哈希校验。
再举个例子:若你设计硬件安全模块,至少该考虑过行锤攻击(rowhammer)吧。
作为程序员,我时刻关注这些问题。尤其编译器/工具链漏洞——一旦开始留意,这类问题其实相当常见。
他在特定意义上提出了合理区分:只要我们正确理解程序,就能完全掌握其行为[0]。但球形奶牛模型(顺带一提,计算机可模拟此模型,意味着程序在某种程度上继承了模型的缺陷,且所有程序都在模拟某种实体)则无法如此断言。
然而这个“只要”条件承担了相当大的工作量。实践中我们极少能完美掌握现实世界的程序。实际操作中,我们对程序行为的认知与实际运行存在偏差,知识体系存在空白等。这种问题自然也困扰着物理系统的数学近似模型。
[0] 甚至这个前提也并非绝对成立。试想并发程序。竞争条件可能引发各种不可预测的怪异结果。即便是对程序的完美认知,也无法预知最终结果。
哎呀!https://entropicthoughts.com/software-never-fails
虽然理论上可能存在完美软件能在完美计算机上永无故障地运行,但现实是:运行它的计算机和受控设备终将失效——问题仅在于何时如何失效,而非是否失效。使用寿命内未发生故障的设备,仅仅是因为使用时间不足以触发故障。
基于此标准,软件开发同样必须聚焦于故障场景。这包括计算机内部故障(如内存缺陷或CPU核心损坏)等考量因素。
过度关注故障分析的问题在于,这种方法忽略了即使系统完全按设计运行时仍会发生的各类损失。分析必须涵盖所有损失——既包括故障(通常是显而易见的案例),也包括非故障(设计错误,往往更难发现)。
另一份关于软件安全军事标准的优秀文档是AOP-52。
其中记载了若干趣闻轶事。我最喜欢的是核认证超音速飞机在集成新子系统时发现的潜在缺陷:所有机载飞行计算机在亚音速转超音速时集体崩溃。所幸飞机惯性足够强,得以在跨音速边界区“挺过”所有飞行计算机同时瘫痪的危机。
这个故事的启示是:软件开发人员必须掌握理解系统物理特性的专业术语。
我通常发现,那些寻求“最佳实践”的人往往在逃避“坐下来思考软件及其在整体系统中的作用”这一环节。
完全正确。以航空电子领域广泛采用的DO-178C标准为例,它几乎未涉及编程方法,重点在于确保软件正确实现了系统级需求。
我认为这些标准的核心价值在于:当项目提案出现时,能评估其重要性等级,从而在理想状态下获得充足且匹配的资源支持,或直接终止项目。
但愿如此。我的实际经历却并非如此。常见情况是随意从开发计划中削减内容,直到资源限制看似满足,却很少考虑最终方案是否合理。这还是有计划的情况。有时这些系统仅凭主观判断被随意分配等级,期待后续有人修正错误等级——这种做法的效果和写注释的待办事项差不多。
我认为那些花哨的方法论和流程,本质上是为“坐下来思考软件”而设计的优化手段——尤其在多人开发团队中。
核心工作始终发生在接口处。这些方法论能帮助管理人与人、机器与产品之间的交互界面。
>全面梳理代码与外部世界的所有交互方式本就困难重重。
长期维护这份清单更是难上加难。
这属于伪宗教崇拜。我们常在“敏捷”实践中看到同样现象——它往往沦为借口,让人们继续按原计划行事。
他们只想要收益,却对真正有效的措施避之不及。
“尽管标准稍显复杂…”
若你读过MIL-STD-882E中的软件控制类别定义,就会明白本文作者给出的定义纯属个人解读。882E的实际定义简直混乱不堪——同一类别存在多重矛盾定义,本意澄清的括号说明反而更添迷雾。天啊…
我更倾向于Alistair Cockburn在其清晰方法论中提出的“关键性”分类法[1](有趣的是,数百个模仿者中竟无人采用——该概念仅见于原著第240页左右):
“”“ 第二个重要维度是关键性,即未被发现缺陷可能造成的损害:舒适度损失(C)、可支配资金损失(D)、必需资金损失(E)及生命损失(L)。”“”
(我的重述):他指出,越是深入该列表,制造方式就应越严苛/规范。从初期的“无所不包”到最终的“绝无例外”。
[1] https://www.researchgate.net/publication/234820806_Crystal_c…
说实话,我才不会听那些每30天不重启机器就会罢工的人的建议。
要是项目经理当初写了这个需求,说不定就能获得更长的运行时间了!