预计阅读本页时间:-
1.5.3 文件
实际上,支持操作系统的另一个关键概念是文件系统。如前所述,操作系统的一项主要功能是隐藏磁盘和其他I/O设备的细节特性,并提供给程序员一个良好、清晰的独立于设备的抽象文件模型。显然,创建文件、删除文件、读文件和写文件等都需要系统调用。在文件可以读取之前,必须先在磁盘上定位和打开文件,在文件读过之后应该关闭该文件,有关的系统调用则用于完成这类操作。
为了提供保存文件的地方,大多数操作系统支持目录(directory)的概念,从而可把文件分类成组。比如,学生可给所选的每个课程创建一个目录(用于保存该课程所需的程序),另设一个目录存放电子邮件,再有一个目录用于保存万维网主页。这就需要系统调用创建和删除目录、将已有的文件放入目录中、从目录中删除文件等。目录项可以是文件或者目录,这样就产生了层次结构——文件系统,如图1-14所示。

进程和文件层次都可以组织成树状结构,但这两种树状结构有不少不同之处。一般进程的树状结构层次不深(很少超过三层),而文件树状结构的层次常常多达四层、五层或更多层。进程树层次结构是暂时的,通常最多存在几分钟,而目录层次则可能存在数年之久。进程和文件在所有权及保护方面也是有区别的。典型地,只有父进程能控制和访问子进程,而在文件和目录中通常存在一种机制,使文件所有者之外的其他用户也可以访问该文件。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
目录层结构中的每一个文件都可以通过从目录的顶部,即根目录(root directory)开始的路径名(path name)来确定。绝对路径名包含了从根目录到该文件的所有目录清单,它们之间用正斜线隔开。如在图1-14中,文件CS101路径名是/Faculty/Prof.Brown/Courses/CS101。最开始的正斜线表示这是从根目录开始的绝对路径。顺便提及,在MS-DOS和Windows中,用反斜线(\)字符作为分隔符,替代了正斜线(/),这样,上面给出的文件路径会写为\Faculty\Prof.Brown\Courses\CS101。在本书中,我们一般使用路径的UNIX惯例。
在实例中,每个进程有一个工作目录(working directory),其中,路径名不以斜线开始。如在图1-14中的例子,如果/Faculty/Prof.Brown是工作目录,那么Courses/CS101与上面给定的绝对路径名表示的是同一个文件。进程可以通过使用系统调用指定新的工作目录,从而变更其工作目录。
在读写文件之前,首先要打开文件,检查其访问权限。若权限许可,系统将返回一个小整数,称作文件描述符(file descriptor),供后续操作使用。若禁止访问,系统则返回一个错误码。
在UNIX中的另一个重要概念是安装文件系统。几乎所有的个人计算机都有一个或多个光盘驱动器,可以插入CD-ROM和DVD。它们几乎都有USB接口,可以插入USB存储棒(实际是固态磁盘驱动器)。为了提供一个出色的方式处理可移动介质,UNIX允许把在CD-ROM或DVD上的文件系统接入到主文件树上。考虑图1-15a的情形。在mount调用之前,根文件系统在硬盘上,而第二个文件系统在CD-ROM上,它们是分离的和无关的。

然而,不能使用在CD-ROM上的文件系统,因为上面没有可指定的路径。UNIX不允许在路径前面加上驱动器名称或代码,那样做就完全成了设备相关类型了,这是操作系统应该消除的。代替的方法是,mount系统调用允许把在CD-ROM上的文件系统连接到程序所希望的根文件系统上。在图1-15b中,CD-ROM上的文件系统安装到了目录b上,这样就允许访问文件/b/x以及/b/y。如果当CD-ROM安装好,目录b中有任何不能访问的文件,则是因为/b指向了CD-ROM的根目录。(在开始时,不能访问这些文件似乎并不是一个严重问题:文件系统几乎总是安装在空目录上。)如果系统有多个硬盘,它们也可以都安装在单个树上。
在UNIX中,另一个重要的概念是特殊文件(special file)。提供特殊文件是为了使I/O设备看起来像文件一般。这样,就像使用系统调用读写文件一样,I/O设备也可通过同样的系统调用进行读写。有两类特殊文件:块特殊文件(block special file)和字符特殊文件(character special file)。块特殊文件指那些由可随机存取的块组成的设备,如磁盘等。比如打开一个块特殊文件,然后读第4块,程序可以直接访问设备的第4块而不必考虑存放该文件的文件系统结构。类似地,字符特殊文件用于打印机、调制解调器和其他接收或输出字符流的设备。按照惯例,特殊文件保存在/dev目录中。例如,/dev/lp是打印机(曾经称为行式打印机)。
在本节中讨论的最后一个特性既与进程有关也与文件有关:管道。管道(pipe)是一种虚文件,它可连接两个进程,如图1-16所示。如果进程A和B希望通过管道对话,它们必须提前设置该管道。当进程A想对进程B发送数据时,它把数据写到管道上,仿佛管道就是输出文件一样。进程B可以通过读该管道而得到数据,仿佛该管道就是一个输入文件一样。这样,在UNIX中两个进程之间的通信就很类似于普通文件的读写了。更为强大的是,若进程要想发现它所写入的输出文件不是真正的文件而是管道,则需要使用特殊的系统调用。文件系统是非常重要的。我们将在第6章,以及第10章和第11章中具体讨论它们。
