在云栈社区的分享中,我们常探讨系统设计的源头。接续上篇对UNIX文件系统的梳理,本篇将继续解读这份珍贵的1972年笔记,聚焦其I/O设计与进程控制思想,看看这些早期决策如何深远地影响了后续半个世纪的系统架构。
特殊文件 (Special Files)
文件系统中最有趣的概念之一是“特殊文件”。
某些文件并不指向磁盘文件,而是指向 I/O 设备。按照惯例,这类特殊文件 reside (驻留) 在一个特定的目录中,尽管这不是必须的。当读取或写入特殊文件时,它所指向的设备就会被激活。例如,所有连接到打字机的通信接口都有与之关联的特殊文件。因此,只要你有权限,任何人都可以通过向另一个用户的特殊文件写入信息来发送消息。
系统中还有指向纸带阅读器/穿孔机、201 Dataphone、控制台以及系统上任何其他设备的特殊文件。我们努力使这些特殊文件的行为与普通磁盘文件完全一致。这意味着程序通常无需知道它们是在读写设备还是在读写磁盘文件。
I/O 系统调用
用于 I/O 的系统调用设计得既简单易用又高效。这里没有类似于 Honeywell 机器上的 GEFRC 或 IBM OS/360 中的“访问方法”(access methods) 的概念,因为直接使用系统入口点非常直观。
文件被统一视为由字节流组成;系统对其内容不做任何假设。因此,文件的结构完全由读写它们的程序控制。 例如,一个 ASCII 文本文件仅仅是一个由换行符分隔的字符流。“物理记录”的概念被很好地隐藏了起来。
例如,读取文件的系统入口点只有三个参数:被读取的文件、信息存放的位置、以及所需的字节数。同样,写入调用也只需指定目标文件、信息所在位置以及要写入的字符数。系统会自动根据需要将要读取或写入的信息分割成物理块。
I/O 调用在表面上也是同步的;也就是说,例如当写入操作发生时,对用户而言,写入似乎已经完成。实际上,系统内部包含缓冲区来暂存信息,因此物理写入可能会延迟。
“随机”I/O 和顺序 I/O 之间没有区别。读写调用在本质上是顺序的,例如,如果你从文件中读取了 100 个字节,下一次读取调用将返回紧接着上次读取位置之后的字节。不过,也可以通过“seek”(寻道) 调用来移动读取指针,从而以任意顺序读取文件。
我必须说明,忽略物理记录大小的事实并不总是可取的。一次只读取一个字符的程序显然处于劣势,这不仅仅是因为系统开销。因此,I/O 密集型的程序最好以物理记录大小的倍数进行读写(恰好统一为 512 字节)。但这只是出于效率考虑,而非逻辑上的强制要求。
问题与局限 (PROBLEMS)
我之前提到过,UNIX 并不特别适合涉及海量数据的应用。原因如下:文件大小限制为 64K 字节。这个限制的理由并不特别充分,主要与 PDP-11 的字长为 16 位这一事实有关。
有几个方法可以绕过这个问题。
其中之一是将一个大的逻辑文件拆分为多个较小的实际文件。这种方法在一定时间内是有效的。这里的限制在于目录是以线性方式搜索的。因此,如果文件数量巨大,搜索目录以找到其中的文件可能会非常耗时。到目前为止,我们还没有注意到这会成为一个实际问题,但这确实是一个令人担忧的隐患。
解决小文件限制的另一种方法是将整个磁盘作为一个特殊文件来使用。出于各种原因,当整个磁盘驱动器作为特殊文件访问时,不会出现大小限制。因此,你可以编写一个管理自身数据的程序——实际上就是它自己专用的文件系统——并期望获得合理的结果。
这再次回到了通用系统与专用系统的讨论:只要额外的劳动成本值得,自行进行数据管理可能效率更高。
进程控制 (PROCESS CONTROL)
如前所述,UNIX 的第二部分是关于进程控制的。在 UNIX 中,进程 simply (仅仅) 是程序的执行。每个用户至少有一个代表其工作的进程:它的任务是读取用户的打字机输入,并将输入的内容解释为对系统的命令。与该进程关联的程序称为 Shell,它拥有许多有价值的功能,包括 I/O 重定向。这使得你可以运行那些原本输出到打字机的程序,并将它们的输出重定向到一个文件中。
我不打算深入细节,只想说明,无论是通过使用 Shell 还是在程序内部,都可以创建一个异步运行的进程来执行任何指定的程序。
总结 (SUMMARY)
如果你有兴趣使用 UNIX,有几点需要注意:
首先,关于 PDP-11 硬件:
PDP-11 虽然可能比大多数人意识到的更强大,但它并不是一台大型机器:PDP-11 最多只能容纳 28K 个 16 位字的核心内存。
此外,PDP-11/20 没有硬件保护功能:任何用户随时都可能因为执行了一个包含各种 bug 的程序而导致系统崩溃。这一事实在程序开发期间尤为重要。
PDP-11/45 基本上以极高的性价比解决了这两个问题——考虑到总系统成本,它比 11/20 贵不了多少。它拥有硬件分段功能,并可挂载 256K 的核心内存。由于我们将是最早获得 11/45 的单位之一,所以在它到货后不久,肯定会有运行在其上的 UNIX 版本。(不过具体日期仍不确定。)
或许更重要的是,目前 UNIX 本质上是一个“双人操作”的系统。 任何计划安装 UNIX 的人都应该拥有一些相当高水平的编程人才,因为几乎肯定需要进行一些修改。我们能花在为新的 UNIX 用户工作或提供建议上的时间是有限的。文档虽然存在,但似乎永远不够完整。
回看这份笔记,UNIX 的设计者们在资源极度受限的条件下,依然坚持了“一切皆文件”和简单统一的I/O系统抽象。这些思想不仅成功运行于PDP-11,更成为后续操作系统设计的基石。同时,笔记也坦诚地揭示了早期系统的局限性,如文件大小限制和缺乏硬件保护,这些正是推动进程控制与硬件共同演进的动力。理解这段历史,能让我们更深刻地体会当下系统设计中每一个选择背后的权衡与智慧。