Microsoft |从 FDISK 与 ATTRIB 读懂 MS-DOS:一份基于源码证据的经典操作系统工程审阅
Microsoft |从 FDISK 与 ATTRIB 读懂 MS-DOS:一份基于源码证据的经典操作系统工程审阅
评测对象:Microsoft MS-DOS 开源源码
仓库:https://github.com/microsoft/MS-DOS
固定提交:2d04cacc5322951f187bb17e017c12920ac8ebe2
评测类型:证据驱动的只读静态工程审阅
作者:Valhalla Matrix 治理实验室本文未执行项目构建、测试、依赖扫描或运行时验证。文中结论仅适用于上述固定源码快照。源码统计用于导航,不等同于性能、质量、安全性或可维护性评分。
一、写在前面:为什么今天还要阅读 MS-DOS 源码?
在现代开发者眼中,MS-DOS 似乎已经属于“计算机历史”。
它没有现代操作系统常见的图形化桌面、包管理器、网络服务框架和自动化测试体系。但如果从系统软件工程的角度重新审视,MS-DOS 仍然非常值得阅读。
原因在于,它把许多今天依然存在的系统问题,以更直接、更少抽象的方式暴露了出来:
- 命令行参数如何解析;
- 用户输入如何驱动程序状态变化;
- 文件和磁盘如何被访问;
- 错误如何通过返回值、消息和信号处理表达;
- 交互式菜单如何组织复杂操作;
- 设备操作失败后如何处理;
- 在有限资源环境中,程序如何完成实际任务。
本次评测没有试图回答“MS-DOS 是否适合现代生产环境”,因为静态源码不足以支持这样的结论。
本文真正关注的是:
从 FDISK 和 ATTRIB 等命令模块中,我们能够观察到怎样的系统软件工程结构?
二、结论先行:源码可读性明确,现代工程证据有限
基于固定提交:
2d04cacc5322951f187bb17e017c12920ac8ebe2
静态扫描得到以下结果:
| 指标 | 观测值 |
|---|---|
| 受支持源文件 | 148 |
| 一级模块根 | 1 |
| 主要源码目录 | v4.0 |
| 抽样源码文件 | 12 |
| 抽样声明 | 48 |
| 抽样分支 | 807 |
| 抽样循环 | 268 |
| 抽样异常路径 | 12 |
| 异步线索 | 0 |
| 构建与依赖文件 | 0 |
| 测试文件线索 | 0 |
语言扫描结果为:
{
"C/C++": 88,
"C": 60
}
需要说明,C/C++ 与 C 是扫描器的分类标签,不应直接理解为现代意义上的 C 与 C++ 混合工程。实际源码阅读呈现出明显的传统 C 风格系统程序特征。
综合判断可以概括为:
MS-DOS 源码快照具有明确的历史研究价值、系统软件教学价值和遗留代码审阅价值,但当前快照缺少可确认的现代构建、测试和依赖验证证据。
因此,它适合:
- 学习早期命令行系统工具;
- 研究磁盘与文件操作;
- 阅读传统 C 程序结构;
- 理解状态分支、错误处理和交互式菜单;
- 设计操作系统原理课程案例;
- 开展遗留系统兼容性研究。
不适合仅凭当前静态统计直接得出:
- “代码安全”;
- “可以在现代系统直接编译”;
- “项目具备完整测试体系”;
- “可以直接用于生产环境”。
三、仓库结构:一个高度集中的经典系统源码快照
当前仓库的一级模块结构非常集中:
Repository
└── v4.0
主要源码位于:
v4.0/src
其中可以定位到多个 DOS 命令和系统组件。此次抽样阅读主要覆盖:
v4.0/src/CMD/FDISK/MAIN.C
v4.0/src/CMD/FDISK/MAINMENU.C
v4.0/src/CMD/ATTRIB/ATTRIB.C
v4.0/src/CMD/ATTRIB/ATTRIB.H
v4.0/src/CMD/ATTRIB/MSGRET.H
v4.0/src/CMD/ATTRIB/PARSE.H
从现代软件架构视角看,它并不是一个具有大量一级服务、组件和子仓库的复杂平台,而是一个围绕操作系统命令和底层资源组织的集中式源码结构。
可以将其抽象为:
这个模型虽然简单,却准确体现了早期系统工具的基本运行方式:
- 进入命令;
- 读取参数或初始化终端环境;
- 根据输入选择执行路径;
- 直接访问文件系统、磁盘或设备;
- 通过返回值、消息和状态判断结果;
- 返回菜单或结束进程。
与现代 Web 服务相比,它没有复杂的中间件和服务编排,但对外部资源的直接操作更明显,程序行为也更接近底层系统。
四、重点模块一:FDISK 如何组织高风险磁盘操作?
FDISK 是此次静态审阅中最具代表性的模块之一。
主要文件包括:
v4.0/src/CMD/FDISK/MAIN.C
v4.0/src/CMD/FDISK/MAINMENU.C
静态抽取到的声明包括:
main
signal
get_yes_no_values
init_video_information
clear_screen
do_main_menu
display
从这些名称可以看出,FDISK 至少包含以下职责:
- 程序入口;
- 信号处理;
- 用户确认;
- 显示环境初始化;
- 屏幕清理;
- 主菜单;
- 交互式显示。
其主要控制流程可以概括为:
程序启动
↓
初始化显示环境
↓
进入主菜单
↓
读取用户选择
↓
执行磁盘相关操作
↓
进行确认或错误处理
↓
返回菜单或退出
4.1 FDISK 的核心不是“菜单”,而是状态控制
FDISK 这类工具的危险性来自它会影响磁盘结构和系统状态。
因此,程序必须同时处理三类状态:
用户状态:用户选择了什么操作?
设备状态:磁盘当前处于什么状态?
操作状态:上一步是否成功?
这三类状态会形成大量分支。例如:
- 用户输入是否合法;
- 是否确认继续;
- 目标磁盘是否存在;
- 目标分区是否已存在;
- 操作是否成功;
- 操作失败后是否返回菜单;
- 收到中断后是否终止当前流程。
这也是为什么不能单纯根据“代码行数少”判断早期系统工具简单。底层工具的代码规模可能不大,但每一个分支都可能对应真实设备状态和不可逆操作。
4.2 FDISK 对现代系统软件的启发
今天的磁盘管理工具仍然面临类似问题:
- 分区操作前需要二次确认;
- 破坏性操作需要清晰提示;
- 输入参数必须严格校验;
- 设备状态需要及时刷新;
- 失败后需要保留可恢复路径;
- 日志和错误信息必须足够准确。
现代工具可能使用图形界面、RPC、事务机制或异步任务,但底层问题并没有消失。
从 FDISK 源码阅读中,值得重点学习的不是某一段旧式 C 代码,而是:
高风险系统操作必须把用户意图、设备状态和操作结果明确区分。
五、重点模块二:ATTRIB 如何处理命令行、文件和属性?
ATTRIB 模块负责处理文件属性,是另一个具有代表性的 DOS 命令工具。
相关文件包括:
v4.0/src/CMD/ATTRIB/ATTRIB.C
v4.0/src/CMD/ATTRIB/ATTRIB.H
v4.0/src/CMD/ATTRIB/MSGRET.H
v4.0/src/CMD/ATTRIB/PARSE.H
抽取到的函数包括:
inmain
main
Parse_it
Make_fspec
从函数命名看,ATTRIB 的主要处理链路可以概括为:
命令行输入
↓
参数解析
↓
生成文件规格
↓
匹配目标文件
↓
读取或修改文件属性
↓
输出结果
本次抽样统计显示,ATTRIB 模块包含:
| 指标 | 观测值 |
|---|---|
| 分支 | 204 |
| 循环 | 98 |
| 异常路径 | 3 |
这说明它需要处理较多输入组合和文件状态。
5.1 参数解析是命令行工具的第一道边界
对于 ATTRIB,应该重点关注以下输入:
- 设置属性;
- 清除属性;
- 指定单个文件;
- 使用通配符;
- 指定路径;
- 目标文件不存在;
- 参数格式错误;
- 文件属性组合不合法。
命令行程序看似简单,但参数解析经常是系统工具中最容易积累边界问题的地方。
一个可靠的解析流程至少应明确:
原始参数
↓
词法切分
↓
选项识别
↓
路径和文件规格解析
↓
参数组合校验
↓
生成内部操作对象
如果解析与文件操作混杂在一起,后续测试和错误定位都会变得困难。
5.2 文件规格生成是重要审阅点
Make_fspec 这一名称值得特别关注。
它可能承担路径、文件名和通配符组合的构造工作。此类逻辑需要重点检查:
- 路径长度边界;
- 驱动器号处理;
- 当前目录处理;
- 通配符展开;
- 空路径与非法路径;
- 目录和文件的区分;
- 特殊设备名;
- 文件不存在时的错误路径。
即使某段代码在原始 DOS 环境中行为正确,也不能直接推断它在现代兼容层、模拟器或移植环境中仍然表现一致。
六、如何正确理解“807 个分支、268 个循环”?
此次抽样的结构统计为:
声明:48
分支:807
循环:268
异常路径:12
异步线索:0
这些数字可以帮助我们安排阅读顺序,但不能作为代码质量评分。
6.1 它们可以说明什么?
可以用于判断:
- 哪些文件包含更多控制流;
- 哪些模块可能需要更多边界场景;
- 哪些代码更适合优先进行人工审阅;
- 哪些区域可能与交互、批量处理或错误恢复有关。
例如:
分支较多
→ 优先阅读输入校验和状态转换
循环较多
→ 优先检查终止条件和批量文件处理
I/O 较多
→ 优先检查路径、句柄和失败恢复
异常路径较多
→ 优先检查返回码、信号和资源清理
6.2 它们不能说明什么?
不能直接推出:
- 圈复杂度;
- 缺陷数量;
- 运行性能;
- 内存安全;
- 可维护性;
- 安全等级;
- 实际执行路径。
原因包括:
- 宏展开可能影响统计;
- 头文件与实现文件的结构不同;
- 扫描器的语法分类存在边界;
- 静态抽样不覆盖全部文件;
- 代码是否被调用需要调用链确认;
- 条件分支不等于所有路径都会运行。
因此,最稳妥的表述是:
结构统计是源码导航指标,不是工程质量评分。
七、文件与磁盘 I/O:MS-DOS 代码审阅的核心风险面
抽样源码中识别到 230 次文件或网络 I/O 相关符号线索。
对于 MS-DOS,这类线索属于核心功能范围,因为项目直接面对:
- 文件;
- 目录;
- 磁盘;
- 设备;
- 路径;
- 命令行输出。
但需要注意,词汇扫描将“文件 I/O”和“网络 I/O”归入同一类,并不代表项目存在现代网络服务能力。这里更准确的解释是:
当前抽样中观察到大量与文件、磁盘、设备和输入输出相关的线索;是否存在网络行为,需要结合具体调用链确认。
7.1 路径与文件名边界
建议重点核对:
- 文件名长度限制;
- 路径长度限制;
- 驱动器号;
- 当前目录;
- 通配符;
- 特殊设备名;
- 目录与普通文件的差异;
- 大小写和字符集处理。
7.2 文件句柄和资源生命周期
需要确认:
- 打开失败是否及时返回;
- 所有成功打开的文件是否最终关闭;
- 循环处理大量文件时是否存在资源耗尽;
- 用户中断后是否释放资源;
- 错误路径是否遗漏清理操作。
7.3 磁盘操作的不可逆风险
对于 FDISK 等模块,应特别关注:
- 操作前是否有明确确认;
- 操作目标是否经过再次校验;
- 写入失败如何处理;
- 部分成功如何恢复;
- 操作过程中断电或中断会发生什么;
- 错误信息是否足以帮助用户判断结果。
这些问题仅靠静态文件统计无法回答,必须在隔离环境中使用磁盘镜像或模拟设备验证。
八、这份静态评测中,哪些地方需要修正?
原始材料整体强调了“静态证据边界”,这是正确的。但为了提高报告质量和可审计性,仍需要统一几个口径。
8.1 构建、测试、CI 证据存在口径冲突
一页纸部分称:
构建、测试与 CI 等静态证据均已定位。
但详细资产面板显示:
构建与依赖文件:0
测试文件线索:0
因此,不应继续使用“构建、测试与 CI 已定位”这一表述。
更严谨的写法是:
已完成源码和模块定位;当前静态评测未确认可用的构建、测试和 CI 证据,仍需人工检索和实际执行验证。
这是报告中最需要修正的内容。
8.2 “部分完整”应该改为证据矩阵
建议使用如下矩阵替代笼统评级:
| 证据类型 | 状态 | 当前依据 |
|---|---|---|
| 提交可复现性 | 已确认 | 固定 Commit SHA |
| 源码清单 | 已确认 | 148 个受支持源文件 |
| 模块边界 | 部分确认 | 主要边界为 v4.0 |
| 构建流程 | 未确认 | 未发现构建/依赖文件 |
| 自动化测试 | 未确认 | 未发现测试文件线索 |
| CI/CD | 未确认 | 未列出工作流文件 |
| 依赖安全 | 未确认 | 未执行依赖扫描 |
| 许可证信息 | 未确认 | 当前材料未定位 |
这种写法能够让读者明确知道:项目究竟“确认了什么”,又“没有确认什么”。
8.3 头文件与实现文件应分开统计
抽样文件同时包含:
.C 实现文件
.H 头文件
建议分别统计:
实现文件:函数、分支、循环、I/O
头文件:宏、类型、声明、常量
这样可以避免把头文件声明与实现文件控制流混在一起,提升统计解释的准确性。
8.4 “请求或路由”需要改成“命令入口与分派”
MS-DOS 是命令行操作系统。报告中的“请求或路由”容易让读者联想到 HTTP API 或微服务网关。
建议改为:
命令入口、参数解析与菜单分派相关线索。
同样,文件或网络 I/O 也应拆成:
文件系统 I/O
磁盘或设备 I/O
终端输入输出
网络 I/O
只有在确认实际网络调用后,才能使用“网络 I/O”。
九、如何在隔离环境中验证 MS-DOS 源码?
当前快照没有显示可确认的构建和测试配置,因此不建议直接在现代宿主机上尝试“裸编译”。
更合理的验证顺序如下。
第一步:定位原始构建入口
建议检索:
Makefile
makefile
build.bat
compile.bat
README
Dockerfile
CMakeLists.txt
同时确认:
- 项目需要哪种 C 编译器;
- 是否依赖 DOS 专用工具链;
- 是否需要模拟器;
- 是否提供交叉编译方式;
- 是否存在预构建工具或二进制资产。
第二步:优先验证 ATTRIB
ATTRIB 的验证风险低于真实磁盘分区操作,建议先测试:
ATTRIB 参数解析
ATTRIB 文件属性读取
ATTRIB 文件属性修改
ATTRIB 通配符处理
ATTRIB 非法路径处理
ATTRIB 不存在文件处理
测试目录可以使用隔离的模拟文件系统或 DOS 镜像。
第三步:再验证 FDISK 的非破坏性路径
FDISK 涉及磁盘操作,必须使用:
- 空白磁盘镜像;
- 虚拟机;
- DOSBox 或兼容模拟环境;
- 快照和可回滚环境。
禁止直接对真实生产磁盘执行任何未经验证的命令。
第四步:补充现代静态分析
建议使用适配旧式 C 代码的工具检查:
- 缓冲区边界;
- 整数溢出;
- 未初始化变量;
- 返回值遗漏;
- 文件句柄泄漏;
- 信号处理;
- 未定义行为;
- 旧式指针和类型转换;
- 宏副作用。
但工具报告也必须经过人工复核。旧式代码中的兼容性写法不一定都是实际缺陷。
十、MS-DOS 源码适合哪些读者?
1. 操作系统学习者
可以通过 FDISK 和 ATTRIB 理解:
- 命令行程序入口;
- 文件系统操作;
- 设备交互;
- 错误处理;
- 状态分支;
- 终端交互。
2. C 语言学习者
相比现代大型项目,MS-DOS 源码的运行边界更加直接,适合观察:
- 函数组织;
- 头文件和实现文件;
- 宏与常量;
- 返回值错误处理;
- 循环和分支;
- 文件 I/O。
3. 遗留系统维护人员
它可以作为历史代码审阅案例,用于思考:
- 如何识别隐式约定;
- 如何处理缺少测试的老代码;
- 如何建立现代构建环境;
- 如何设计兼容性验证;
- 如何在不破坏原有行为的情况下进行重构。
4. 系统软件与安全研究者
重点可放在:
- 命令解析边界;
- 文件名和路径处理;
- 设备操作;
- 中断和信号;
- 资源释放;
- 不可逆操作的确认机制。
十一、最终评价:源码很有价值,但不要把历史研究误写成现代质量认证
MS-DOS 源码的价值,并不在于它是否符合今天的工程规范。
它的价值在于:它让我们看到一个操作系统命令工具如何直接面对用户、文件系统和磁盘设备。
从 FDISK 可以观察到:
启动
-> 显示初始化
-> 主菜单
-> 用户确认
-> 磁盘操作
-> 错误处理
-> 返回或退出
从 ATTRIB 可以观察到:
命令行参数
-> 参数解析
-> 文件规格生成
-> 文件遍历
-> 属性读取或修改
-> 结果输出
这两条链路虽然来自经典 DOS 环境,但其中的工程问题至今仍然存在:
- 输入是否可信;
- 状态是否明确;
- 外部资源操作是否可控;
- 错误是否可恢复;
- 失败后是否释放资源;
- 高风险操作是否需要确认;
- 代码是否有足够的验证证据。
综合评价如下:
本次 MS-DOS 静态评测具有较高的源码导航和历史研究价值,但现代工程证据不足。源码快照可复现,模块和重点代码可以定位;构建、测试、CI、依赖和安全状态尚未确认。
最稳妥的结论不是“这份代码安全”或“这份代码质量差”,而是:
它适合阅读、研究和验证,不适合在缺少构建与运行证据的情况下直接作出生产决策。
结语:从老系统源码中学习真正稳定的工程原则
技术栈会变化。
从 DOS 到 Linux,从本地命令到云服务,从单机程序到分布式系统,工具和语言不断演进。
但一些工程原则始终没有变化:
- 先明确输入,再执行操作;
- 把用户状态、系统状态和操作结果分开处理;
- 对外部资源操作进行失败设计;
- 对不可逆操作增加确认和回滚思维;
- 用测试验证边界,而不是只验证正常路径;
- 用固定版本和完整环境保存复现条件;
- 区分源码观察、运行事实和上线结论。
这也是阅读 MS-DOS 源码最值得带走的收获:
优秀的系统软件,不只是能够完成任务,更要能够在输入异常、资源失败和状态变化时,保持行为可理解、结果可判断。
参考信息
- GitHub 仓库:
https://github.com/microsoft/MS-DOS - 固定提交:
2d04cacc5322951f187bb17e017c12920ac8ebe2 - 重点源码:
v4.0/src/CMD/FDISK/MAIN.Cv4.0/src/CMD/FDISK/MAINMENU.Cv4.0/src/CMD/ATTRIB/ATTRIB.Cv4.0/src/CMD/ATTRIB/ATTRIB.Hv4.0/src/CMD/ATTRIB/MSGRET.Hv4.0/src/CMD/ATTRIB/PARSE.H
关键词
MS-DOS、FDISK、ATTRIB、操作系统源码、C语言、文件系统、磁盘管理、遗留代码审阅、静态代码分析、系统软件工程
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)