打字猴:1.700436071e+09
1700436071 UNIX传奇:历史与回忆 [:1700434689]
1700436072 UNIX传奇:历史与回忆 4.1 文件系统
1700436073
1700436074 文件系统是操作系统的一部分,负责管理磁盘等次级存储设备上的信息。过去有好些年,磁盘是基于磁性旋转介质的精密机械装置,如今最常见的是固态硬盘和USB闪存盘等没有可移动部件的集成电路。
1700436075
1700436076 通过Windows上的资源管理器(Explorer)和macOS上的访达(Finder)等程序,我们已经熟识这种信息存储的抽象视图。再往下是管理物理硬件上各种信息的大量软件,它们跟踪每个部分的位置,控制访问,使其有效地进行读写,并确保其始终处于持续一致的状态。
1700436077
1700436078 在Multics之前,大多数操作系统充其量只是提供了复杂又不规则的文件系统来存储信息。Multics文件系统比当时的其他文件系统更通用、更规则、更强大,但相应地也很复杂。肯开发的Unix文件系统从Multics中汲取了养分,但明显更简单。其整洁、优雅的设计多年以来被广泛使用和模仿。
1700436079
1700436080 每个Unix文件都只是一系列字节的组合。文件内容的结构或组织方式只由处理它的程序决定,文件系统本身并不关心文件中的内容。这意味着任何程序都可以读取或写入任何文件。如今看来,这个概念似乎显而易见,但在早期的系统中并不总受青睐,因为早期系统有时会对文件中的信息格式以及程序如何处理这些信息施加限制。道格·麦基尔罗伊讲过一个例子:
1700436081
1700436082 “源代码是一种特别的文件类型,不同于其他数据文件。编译器可以读取源代码,编译好的程序可以读取和写入‘数据’。因此,Fortran程序的创建和读取往往与其他文件的创建和读取隔离开来,编辑和输出的方式完全不同。这就排除了使用程序生成(甚至简单复制)Fortran程序的可能性。”
1700436083
1700436084 Unix没做区分:任何程序都可以处理任何文件。如果程序处理不了文件,例如,试图将Fortran源文件当作C语言程序来编译,那和操作系统没有任何关系。
1700436085
1700436086 Unix以目录为单位来组织文件。(其他操作系统通常称之为文件夹。)Unix目录也是文件系统中的一个文件,但其内容由系统本身维护,不由用户程序维护。目录中包含了其下文件的信息,而这些文件又可以是目录。
1700436087
1700436088 Unix目录项包括目录内的文件名、访问权限、文件大小、创建和修改的日期及时间,以及在哪里可以找到文件内容的信息。每个目录下都有两个特殊的目录项,名为“.”(目录本身)和“..”(上层目录),它们的发音分别为“dot”和“dotdot”。根目录是层次结构的顶端,名为“/”。从根目录往下走就能找到任何文件,而从任何文件都可以通过上层目录序列向上找到根目录。因此,本书的文本可以在/usr/bwk/book/book.txt中找到。系统还支持当前目录的概念,因此文件名可以由文件系统中的当前相对位置来定位,而不必列明从根目录开始的完整路径。
1700436089
1700436090 因为目录可以包含子目录,所以文件系统可以深入至任意层。这种嵌套目录和文件的组织方式被称为“分层”文件系统。同样,虽然事后看来优势明显,但在Multics和Unix之前,分层文件系统并没有被广泛使用。例如,有些文件系统限制了嵌套的深度,CTSS就限制只能有两层。
1700436091
1700436092
1700436093
1700436094
1700436095 UNIX传奇:历史与回忆 [:1700434690]
1700436096 UNIX传奇:历史与回忆 4.2 系统调用
1700436097
1700436098 操作系统为运行于其上的程序提供一系列服务,包括启动和停止程序、读取或写入文件中的信息、访问设备和网络连接、报告日期和时间之类信息等。这些服务在操作系统内部实现,正在运行的程序可以通过一种叫作系统调用的机制来获取服务。
1700436099
1700436100 归根结底,系统调用就是操作系统,因为它们定义了系统提供的服务。一套系统调用可能有多个独立的实现,Unix系统和类Unix系统的不同版本就是如此。其他完全不同的操作系统,如Windows,可以提供软件,将Unix系统调用转换为自己的系统调用。而且即使是类Unix系统,也必然会有某一操作系统特有的系统调用。
1700436101
1700436102 第1版Unix只有30多个系统调用,其中大约一半与文件系统有关。由于文件只包含未经释义的字节,所以基本的文件系统接口非常简单,只有5个系统调用,用于打开或创建文件,读写其字节,以及关闭文件。通过使用以下这样的语句,从C语言程序中调用函数访问这些服务。
1700436103
1700436104 fd = creat(filename, perms)
1700436105 fd = open(filename, mode)
1700436106 nread = read(fd, buf, n)
1700436107 nwrite = write(fd, buf, n)
1700436108 status = close(fd)
1700436109
1700436110
1700436111 creat系统调用创建新文件,并设置它的访问权限。通常情况下,访问权限允许或禁止用户、用户所在组和其他所有人读、写及执行文件的能力。这9个权限位[1]用相对较少的机制给出了相当大的控制权。open系统调用打开现有文件,mode指明是读文件还是写文件,filename是层级文件系统中的任意路径。
1700436112 调用open和creat产生的fd值称为文件描述符(file descriptor),是一个非负小整数,在后续的文件读写中使用。read和write系统调用尝试从文件读出或向文件写入n个字节;系统调用返回实际传输的字节数。对于所有这些系统调用,如果返回负值(通常是-1),则表示发生了某种错误。
1700436113
1700436114 顺便说一下,creat系统调用之所以这么拼写[2],只能归咎于肯 · 汤普森的个人品位,没有其他什么好借口。罗布·派克曾经问肯,如果重写Unix,他会做哪些修改。他的答案是什么?“我会在creat后头加上字母e。”
1700436115
1700436116 Unix的另一创新是把磁盘、终端等外围设备都看作文件系统中的文件,磁盘是功能列表中提到的“可拆卸卷”。访问设备的系统调用和访问文件的系统调用是一样的,所以同样的代码既可以操作文件也可以操作设备。当然实际上并没那么简单,因为真实的设备有奇怪的属性要处理,所以还有其他系统调用来处理这些特殊性,尤其是终端的特殊性。这部分系统并不漂亮。
1700436117
1700436118 还有一些系统调用负责设定文件内的位置、确定文件状态等。50年来,这些系统调用都得到了完善,偶尔也有改进,但基本模式很简单,易于使用。
1700436119
1700436120 今天的读者可能很难体会到这一切是做了多大简化之后的结果。早期操作系统中,真实设备的所有复杂情况都会反馈给用户。用户必须知道磁盘名称,了解磁盘的物理结构,如有多少柱面和磁道,以及数据是如何安放在上面。史蒂夫·约翰逊下面这段话让我记起,那时霍尼韦尔主计算机上的分时子系统是多么的笨拙:
[ 上一页 ]  [ :1.700436071e+09 ]  [ 下一页 ]