为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

unix 文件系统

2011-11-06 50页 doc 1MB 35阅读

用户头像

is_269795

暂无简介

举报
unix 文件系统13.3  UNIX概述 UNIX包含一个内核和大量的实用程序。实用程序充当用户和UNIX内核之间的中介。很容易为UNIX系统添加或修改实用程序,对用C语言编写的实用程序更是如此。因此用户可以针对特定需求,方便地"定制"UNIX。UNIX内核非常小,它总是驻留在内存中。它包含大约10 000行C代码以及大约1000行汇编语言代码。内核的大小使得它自己很容易被理解、调试或增强。因为它主要是用C语言编写的,而且大部分供应商都提供了C编译器,所以内核(还有实用程序)可以很方便地移植到其他机器上。只有底层控制硬件的1000行汇编语言代...
unix 文件系统
13.3  UNIX概述 UNIX包含一个内核和大量的实用程序。实用程序充当用户和UNIX内核之间的中介。很容易为UNIX系统添加或修改实用程序,对用C语言编写的实用程序更是如此。因此用户可以针对特定需求,方便地"定制"UNIX。UNIX内核非常小,它总是驻留在内存中。它包含大约10 000行C代码以及大约1000行汇编语言代码。内核的大小使得它自己很容易被理解、调试或增强。因为它主要是用C语言编写的,而且大部分供应商都提供了C编译器,所以内核(还有实用程序)可以很方便地移植到其他机器上。只有底层控制硬件的1000行汇编语言代码要在移植的时候重写。 大多数操作系统是用与硬件相关的汇编语言编写的。同样,在其他操作系统中,只有大量函数可以在内核中使用,而没有使用简单而且不同的实用程序。这使得这些操作系统的内核庞大,而且很难移植。图13-1描述了UNIX环境。如图所示,UNIX中的内核介于实际硬件和大量如shell或编辑器以及其他这样的实用程序之间。应用程序只能通过这些实用程序和内核交互。UNIX内核最终管理和调度硬件。 UNIX除了作为可以方便移植的操作系统之外,围绕它开发的应用程序也可以轻松地移植到其他运行UNIX的机器(或"匣子")上。移植应用程序指的是什么?典型情况下,应用程序包括3个不同部分:已编译的程序、实用程序和它们的运行顺序。例如,工资支付应用程序包括多个已编译好的应用程序,如工资单打印和纳税计算;大量实用程序,如SORT;用命令语言(Command-Language,CL)示的作业步骤顺序,如IBM机器上的JCL或UNIX系统中的Shell脚本。   (点击查看大图)图13-1  UNIX环境 将应用程序从一台UNIX机器移植到另一台UNIX机器意味着要移植所有这三部分。如果目标机的体系结构和源机器的相同,目标代码就可移植。如果体系结构不同,就要重新编译源程序。新机器上的编译器要将源代码转换成新机器的机器指令,但它在生成机器代码时仍可以使用相同的系统调用。这对应用程序和实用程序同样如此。 Shell脚本类似于汇编语言中的宏。本前面章节中已经讨论过这部分内容。当读者想要操作系统逐个轮流执行应用程序时,可以定义多个步骤。每个步骤应指明应用程序或实用程序的运行。该执行要满足一定的条件!因为包含脚本和系统调用的shell命令在这两台机器上相同(这里假定先称其为"UNIX"),所以能够很方便地移植如工资薪水这样的应用程序。如果都要移植,就要注意编程语言中的DBMS接口指令。如果所用的数据库相同,那么就不会有什么问题。 所有这些看上去很好。但现实中,不同版本的UNIX存在很多差别。遗憾的是,这些差别并不局限于UNIX内部或实现细节,但它们符合系统调用及其接口。在某些情况下,用户接口还有轻微差异。这增加了可移植性的难度。 假定UNIX内核只分成两部分:信息管理和进程管理。内存管理可以立刻连接到进程管理,由进程管理驱动。因此,假定内存管理是进程管理的一部分。 可以将大量不同类型的设备连接到运行UNIX的机器上。UNIX内核的信息管理部分包含针对不同设备的驱动程序。当制造出新设备的时候,设备制造商或UNIX操作系统的供应商就会提供支持这些设备的驱动程序。"设备无关的I/O"这个概念极大地推动了这个过程。UNIX中的设备被当作文件。这句话实际上是什么意思呢?UNIX系统的根目录下有一个子目录,名为"/dev",该目录包含多个文件,每个文件对应一个设备。每个文件有类似于普通文件中定义的访问权限。 每个设备文件都很短,它包含该设备的具体特征细节信息。现在考虑一下UNIX中的通用设备驱动程序,在特定时刻这些特性可以作为参数提供给这些通用设备驱动程序以获取"定制的"设备驱动程序。当然,事情并非像前面的概括的那样轻松。但人们可以为设备编写至少类似的通用驱动程序。如果这样的驱动程序是可用的,就可以简单地添加设备。因此,只需在/dev目录下为该设备创建一个文件即可。如果设备有大量不同的特性,也许就要改动通用设备驱动程序或是为/dev目录下创建的文件编写相应的新文件。 例如,设备可以是类似终端这样的字符设备,也可以是类似于磁盘这样的块设备。每个设备都需要运行特定的驱动程序,并提供读写数据用的特定内存缓冲区。因此,对任何设备I/O而言,都要指明设备类型、特性、驱动程序的地址以及为设备保留的内存缓冲区。关于该设备的这些内容以及其他细节按照预定格式或布局存储在/dev目录下该设备的设备文件中。 在UNIX中,如果想要向特定的设备写数据,就要向/dev目录下该设备的设备文件提交进行写操作的系统调用。用户应按照编程语言语法提交一个常用指令。例如,他也许想要给打印机写数据。对应该指令,编译器针对/dev目录下该设备的设备文件生成写操作系统调用。写向该设备文件的系统调用是智能的。在指令运行期间,它提取出包含设备特性和设备驱动程序地址的设备文件的内容,利用该信息调用所需的设备驱动程序等。当为系统添加新设备时,编写该设备的设备驱动程序,并在/dev目录下创建对应的"设备文件"。这就是本书中提到在UNIX中将设备当作文件的含义。 不需要一直使用机器上的所有硬件和设备。记住:需要的硬件和设备越多,操作系统就越大,因为操作系统要包含和加载那么多的驱动程序,要为它们创建很多的缓冲区。因此,通常只为系统指定所需的硬件和设备。该过程被称作"系统生成"(SYSTEM GENERATION)。 UNIX中文件系统是层次结构型的。稍后再讨论它的逻辑实现。UNIX进程要么运行在用户模式下,要么在内核模式下。当发生中断(例如,由于I/O操作完成或定时器时钟中断)或进程执行系统调用时,运行模式从用户模式转换到内核模式。此时,内核开始处理某些例程,除了它们是在内核模式下运行之外,当时运行的进程仍是相同的进程。 进程有不同的优先级,它们可以"智能地"变化。这样,随着时间的推移,受进程约束的I/O就要比受进程约束的CPU具有更高的优先级。具有相同优先级的进程严格按照循环等待法获取自己的CPU时间片。 如果在没有内存可用的情况下想要执行较高优先级进程,在UNIX中常会用到两种技术:一种是交换,将整个进程镜像换出(除了它驻留在内存的部分)。另一种技术是请求页面交换,只将某些页面换出,并且随即创建新进程。这种情况下,这两个进程都继续执行。如今,请求页面交换技术更流行。 内核维护用于管理进程的不同数据结构。例如,它维护一个名为u区(U-area)的数据结构,该数据结构类似于前面讨论的进程控制块(Process Control Block,PCB)。每个进程有一个u区。内核还要为每个进程维护内核堆栈。因此,对每个进程而言,同内核堆栈一样还有一个用户堆栈(User stack)。这些堆栈分别用于进程的用户模式和内核模式,用于存储返回地址或系统调用/函数的参数。有趣的是:用户进程的虚拟地址空间不止包括进程的用户部分,还包括与该进程相关的某些内核数据结构。如果进程处于内核模式,它就可以访问整个地址空间;但如果进程处于用户模式,它就只能访问用户地址空间的用户部分。进程的用户部分包括以下元素或区域。 文本(即编译后的机器指令或代码,例如,COBOL的编译过程区)。 数据(例如,作为COBOL数据区中的FD或工作存储区定义的数据)。 堆栈(用于存储子程序返回地址和参数)。 如果其他某个进程要想使用内存,就可以将这个用户区完全交换出去。用户地址空间的内核部分有一部分(如u区)也可以交换,有一部分不可以交换或是驻留在内存中。驻留在内存中的部分绝对不能交换出去。例如,内核保存了一个进程表,该表针对系统中每个现有的进程有一个条目,它的状态可以是正在运行或准备就绪或被阻塞(正在睡眠)。而不管该进程的状态如何,该进程表绝不可以交换出去,因为它包含了进程调度和交换自身所需的最基本的信息。例如,如果一些内存空间空闲,就要用该表确定换入哪一个进程。表中每个条目都有多个指向该进程u区以及地址空间的用户部分(如文本、数据和堆栈)的指针。图13-2描述了这种情况。该图水平分为两部分:驻留的内容和可交换的内容。它还垂直分为两部分:内核地址空间和用户地址空间。进程表位于内核地址空间的驻留部分。该表针对UNIX"已知的"每个进程有一个条目。如前面讨论的一样,该图给出了表中指向该条目的不同指针。   图13-2  内核地址空间和用户地址空间的对照、 驻留地址空间和可交换地址空间的对照 记住:这些表只是逻辑层的描述。具体的UNIX实现也许要决定在物理层上分割或合并不同的表。文本、数据和堆栈在UNIX中被当作区域(region)。它类似于段。例如,UNIX中多数编译器生成可重入的(reentrant)文本,也就是多个用户可以用该文本的唯一副本。代码很稳定,在运行期间不需要修改。为了实现不同区的共享,就要共享不同的数据结构(例如,每个进程区表)。 图13-3描述了UNIX的不同模块及其相互关系。   (点击查看大图)图13-3  UNIX操作系统中的不同模块及其相互关系 13.4  UNIX文件系统 13.4.1  文件系统的用户观点 UNIX实现了层次结构化文件的系统。在该方案中,目录中可以包含多个文件和子目录。磁盘被分成多个区。每个分区有自己的文件系统。文件系统开始于一个倒置树顶部的根目录。这个根目录下包含多个目录,每个目录又都包含许多文件/子目录等。如图13-4所示。在该图中,矩形代表目录,圆圈代表文件。   (点击查看大图)图13-4  层次结构型文件系统 在UNIX中,文件是字节流,也就是说UNIX中根本没有这个概念。读取定长为500字节记录的应用程序可以向UNIX内核发送请求,以便在它想要读取第一个、第二个、第三个等记录时,通过相对字节号(Relative Byte Number,RBN)0-499、500-999、1000-1499等逐个读取字节。内核会将RBN先转换成逻辑块号(Logic Block Number,LBN),然后再转换成物理块号(Physical Block Number,PBN),之后向磁盘控制器提交必要的指令用以确定读/写磁头的位置,然后再读取想要的扇区。本书已经详细介绍过这个转换过程。因此,将"字节流"转换成记录以及转换为更进一步的字段完全留给应用程序完成。 13.4.2  不同类型的文件(1) UNIX操作系统识别以下4类文件。 1. 常用文件 常用文件可以是常见的文本文件或二进制文件。这里"文本"一词指的是英语中使用的文本。在此不要将其和包含编译代码的进程文本混淆。文本文件可以包含所有的源程序或使用字处理程序编写的文档。这些文本文件通常只包含ASCII码。UNIX操作系统中有一个名为cat的命令,该命令可以在屏幕上显示文本文件的内容。 另一方面,二进制文件包含编译好的程序以及所有其他非文本信息。不必说,二进制文件的任何字节,任一由8位组成的256个组合都可能存在,不管这些组合根据ASCII惯例是否有意义。因此,cat命令不能用于显示二进制文件(cat命令一次得到8位,并且在显示前根据ASCII表翻译这8位信息)。UNIX提供了另一个名为od的命令,它可以显示编译好的对象或二进制文件。od是Octal Dump的英文缩写。od使用程序获得二进制文件,并通过每次提取3位将该文件中的位转换成可打印的八进制字符。该实用程序可用于详细的检查/调试。在根目录下,有一个名为"UNIX"的文件,它包含UNIX自身的二进制代码或目标代码。可以使用"od/UNIX"命令以八进制的形式来显示UNIX自身的文件信息。 2. 目录文件 在UNIX操作系统中,目录也被当作文件。它认为目录是单个文件或多个文件。这表明目录像一个包含多条记录或条目的文件。每个文件、目录中的子目录都有一个条目。条目包含下面的文件/子目录的符号名以及一个指向另一个记录的指针或名为"索引节点"(index node,inode)的数据结构。"inode"保存了与文件/目录相关的信息,如所有者、访问权限、不同的创建和使用情况、修改日期以及用于定位和检索分配给该文件/目录不同块的地址。因此每个文件、目录或子目录包括根目录在内都有一个定长的索引节点记录。索引节点全保存在磁盘上,它们按照0、1、2等顺序编号,这个数字编号作为定位包含文件/目录信息的索引节点的指针。 可以再次参照图13-4。图13-5给出了对应图13-4中所有文件、目录以及子目录的索引节点。这与前面介绍的基本文件目录(Basic File Directory,BFD)很相似。为了让读者更好地理解它们之间的对应关系,虽然图13-5中给出了其对应关系,但实际上索引节点同BFD条目一样都不包含符号文件名。符号名实际上存储在一个名为符号文件目录(Symbolic File Directory,SFD)的文件中,如图13-6所示。 图13-6给出了图13-4中所有目录的目录项。这与前面研究的符号文件目录(SFD)很相似。由图13-5中的"类型"字段可以清晰地看到这一点。例如,索引节点1对应图13-4中所示的目录A。图13-5中的"类型"字段显示这是目录,而不是文件。图13-5中的"地址"字段是包含SFD的文件所对应的磁盘块地址。然而,如果该索引节点对应的是文件而不是目录,那么该"地址"字段就是文件自己所对应的磁盘块地址。 例如,图13-6中索引节点等于1的A的目录给出了A1和A2以及它们的索引节点。如果使用这些编号跟踪图13-5中索引节点号条目,就会发现A1(它的索引节点为4)是一个目录,而A2(它的索引节点为5)是一个文件。诚如所知,"类型"字段指明了这一点。对这两者而言,指向它们的磁盘块地址或指针是在索引节点自身中维护的。如果对索引节点等于4的A1根据该地址读取分配给A1目录文件的块,那么就可以得到图13-6(e)所示的A1目录。现在可以逐条读取目录A1的内容(每个条目是定长的,在某些实现中该长度是14个字符),从而可以查看A1中的任一文件或目录。现在以文件或目录的符号名为键,进行表搜索而访问A1中任一目录或文件的索引节点号。 这之后,可以重复读取该索引节点、获取指针或可以得到实际块的索引节点中的地址这个过程。如果它是A1中的目录,那么就要循环重复该过程,从而遍历层次结构中的全部位置(这就是为什么在UNIX将目录当作文件的原因)。如果它是A1目录中的文件,地址字段就直接指向分配给该文件的数据块。内核现在可以根据该数据块执行地址转换,从而找到要读取的扇区。然后,内核可以指挥控制器读取那些扇区,读出要用的数据。   (点击查看大图)图13-5  针对图13-4的索引节点(BFD) 每个目录有两个固定的条目--一个对应"."条目,另一个对应".."条目。"."表示相同的目录。对它的索引节点编号是针对相同目录的。例如,在图13-6(f)中针对C1的目录,'.'条目保存了7。这是C1目录的索引节点编号,如图13-5和图13-6(d)所示。 '..'对应父目录及其相应索引节点号。例如,目录A1的'..'指明inode编号为1。这是图13-5和13-6(b)所示的A的目录索引节点号。图13-6(b)揭示了A是A1的父目录。图13-6(a)中根目录的'..'给出了inode的编号为0,因为假定根目录就是自身的父目录。所以上溯也就只能到根目录为止。 每个用户有一个主目录。该目录要在系统知道用户时就已经定义好了。此时,用户的主目录按用户名存储在/etc/passwd文件中。"创建用户"的程序提示了 主目录。用户一登录系统后,主目录就成为工作目录或当前目录。当用户登录系统时,查询/etc/passwd文件,然后将用户放置到主目录中。任何时候,用户操作所在的目录都被称作"工作目录"或"当前目录"。UNIX有一个"cd"(更改目录)命令。用户通过该命令可以切换到新目录。例如,参见图13-4,如果将A1定义为用户的home目录,命令"cd /C/C1"就可以将用户移动到该目录。此外,/C/C1被称作绝对路径。此时,C1成为用户当前目录。使用"pwd"命令可以找到当前目录。   (点击查看大图)图13-6  针对图13-4的目录(SFD) 13.4.2  不同类型的文件(2) 如果坐在终端前的用户想要指定一个文件,通常有两种方式可以指定该文件。一种是相对路径名,它可以根据当前目录指定。另一个是绝对路径名,它是从根目录开始指明。通常,不需要输入任何路径名就可以访问当前目录中的文件。 例如,再次参照图13-4,如果A1是当前目录,而且如果希望列出该目录中的文件,就使用UNIX的"ls"命令。 系统会显示以下内容: A11 A12 注意:在"ls"命令中,没有必要提供路径名。 另一方面,如果用户想要在当前目录仍旧是A1的情况下,列举目录C2中的文件,他要提交这样的命令: ls /C/C2 系统会显示以下内容: C21 C22 这种情况下,/C/C2是绝对路径名。如果用户想要列出目录A的内容,当他还在当前目录A1中,用"ls .."(相对路径名)或"ls /A"(绝对路径名)即可。这两者被认为是等价的。".."指的是A1的父目录,本例中A1的父目录也就是图13-4所示的目录A。注意:".."的使用。将其和图13-6(e)给出的A1内容进行比较。在表顶部,有一个针对".."的条目。这是对应A1的父目录。图13-4说明这是目录A。如果想要访问父目录,就会用到".."。针对相对路径名的命令也是采用这样的工作方式。 类似的,如果人们想要从A1也就是当前目录中列出C2目录的内容,他就可以使用"ls ../../C/C2"(相对路径名)或"ls /C/C2"(绝对路径名)。在相对路径名中,第一个".."将系统指向目录A,第二个".."将其指向根目录。之后,"/C/C2"将系统指向C2目录(在相对路径名和绝对路径名情况下都是如此)。 通常,以"/"开始的路径名是绝对路径名,所有其他都是相对路径名。 UNIX提供了另一个功能,也就是链接。链接允许用户对同一个文件使用两个以上的路径名。因此,可以将同一个文件看作属于两个或多个目录。换句话讲,有了链接,就有了包含一个索引节点的唯一物理文件,而这个物理文件可以有多个符号名,(符号)目录中那些条目指向同一个索引节点。 现在再次考虑图13-4。如果要从A1(如它现在所在的位置)以及目录C1访问文件A12,那么需要创建C1到A12的链接。图13-7描述了这种情况。在完成链接之后,有两个链接到该共享文件的绝对路径名。它们分别是:A/A1/A12和/C/C1/A12。实际上,在目录C1中,可以用另一个名字调用相同的文件。如果假定这个名字是F1,那么绝对路径名/A/A1/A12和/C/C1/F1相同。它们都指向唯一的只有一个索引节点的物理文件(本例中该物理文件的索引节点为11,如图13-5所示)。 链接可以实现文件的共享使用,并且可以消除在其他目录中复制同一文件的必要性,而在其他目录中复制相同文件也许很浪费空间。解除链接可以删除以前创建的链表。UNIX提供了系统调用及命令进行链接和解除链接。   (点击查看大图)图13-7  链接 在UNIX系统内部,Link系统调用将符号文件添加给指向同一索引节点的新目录。同样地,它会在被链接文件/目录的索引节点中递增"usage count"(使用情况统计信息)或"number of links"(链接数)字段。例如,链接后C1的目录也许如图13-8所示。将其和图13-6(f)比较,看看添加了哪些内容。   (点击查看大图)图13-8  目录C1 要点:索引节点号为11的同一个文件A12被称作是来自C1目录的F1。因此,解析路径名/A/A1/A12和/C/C1/F1会得到同一个物理文件。 3. 特殊文件 第3类文件是特殊文件。特殊文件是由UNIX维护的,它允许用户将I/O设备当作文件处理。通常情况下,对磁带、磁盘、终端或打印机这样的I/O设备而言,UNIX在"/dev"目录中维护着一个特殊的文件,也就是在根目录下的"dev"目录中保存了所有这些特殊文件。 如果应用程序向终端提交一个"write"(写)指令,UNIX使用的系统调用就和用于写文件的系统调用相同。两者唯一的差别在于这种情况下文件是针对特定设备的特殊文件。对不同设备而言,用于不同文件索引节点中的"地址"字段指向这些特殊文件的内容。除了其他内容之外,特殊文件自身包含了内存缓冲区的地址(对终端而言,就是字符链表或clists)以及针对该终端的设备驱动程序地址。内核访问所需特殊文件的索引节点、获取该地址,然后运行真正的设备驱动程序。但对用户或程序员而言,看上去就像是自己正向"文件"写信息。 4. FIFO文件 UNIX使用FIFO文件实现管道。它是一个被当作字节流的文件,但是采用FIFO方式,也就是说,先写给该文件的字节由FIFO文件最先输出。这就是它被称作"先入先出"(First In First Out,FIFO)的原因。假定某个进程将一条包含多个字节的消息写给这个FIFO文件。同样假定另一个进程读取该文件。那个进程按照消息发送的相同方式接收该消息。因此,"I am hungry"接收时也是"I am hungry",而不是"yrgnuh ma I"。这就是管道的基本原理。 从一个重要的角度而言,FIFO文件不同于其他文件。一旦从FIFO文件或管道中读出数据,就不能再次读取该数据,也就是说数据是瞬时的。 13.4.3  加挂/卸载文件系统 读者知道单个磁盘可以分区从而包含多个文件系统,每个文件系统都有自己的根目录。即使磁盘没有分区,但系统有多个连接的磁盘,就可以有多个文件系统。有时候,需要将文件从一个文件系统复制到另一个文件系统。那么如何实现这个操作呢? 假定系统连接有两个磁盘D1和D2。D1是硬盘,D2是软盘,实际上两者都可以是硬盘或软盘。假定它们拥有如图13-9所示的的文件系统。   图13-9  两个设备上的两个文件系统 假定需要将文件R从D2复制到D1下的目录U,在MS-DOS或VMS中,可以使用的命令就是: cp D2:R D1:/X/U/R 或cp D2:R /X/U/R (如果D1是隐式的)。 UNIX采用了不同的方法。UNIX允许"迁离"D2下的整个目录结构,这就是说,通过使用mount命令将其"加挂"或"嫁接"到D1上特定的目录中,例如Y目录。加挂之后,目录结构如图13-10所示。   图13-10  加挂后的目录结构 现在复制文件R就是一项很简单的工作,通过"统一"文件系统中一个简单的命令即可实现: cp /Y/R /X/U/R UNIX为用户提供了一个选择,让其可以在预先指定的时间加挂或卸载文件系统(例如在上夜班的时候)。UNIX保存了一个配置文件,该文件包含了这些时间和指令。后台进程(被称为daemon)不断检查存储的时间,并在特定时间加挂文件系统。它使用"mount"或"unmount"命令执行该任务。另一种方式就是坐在终端前的系统管理员可以显式地使用"mount"或"unmount"命令完成相同的工作。这些命令在内部提交所用的系统调用,从而执行期望的工作。 加挂通常是在系统管理员引导启动UNIX时完成的。如果要在一个文件系统中支持所有有自己目录的用户,那就会很难。想象一下,每个有包含自己文件系统的移动硬盘的用户或学生。在这种环境中,根据学生的要求加挂/卸载文件系统,UNIX可以支持大量的用户,而文件系统大小可以超过特定限制。因此,有了该功能,UNIX可以支持多个移动硬盘。 加挂功能为系统管理员提供了按照自己的需要改变或调整自己文件系统的灵活性。同样地,它还增加了安全性,因而可以有效地防止在一天当中的某个时刻某些用户使用系统。 13.4.4  重要的UNIX目录/文件(1) 前面已经概括性地介绍了层次结构文件系统。现在介绍UNIX维护的一些重要的目录和文件。这些是UNIX操作系统支持的目录和文件。图13-11给出了其中的一些目录/文件。 (1) ('/')"/"是文件系统的根目录。 (2) /bin (二进制) 该目录包括UNIX实用程序的编译后可执行的或二进制代码。有时候,这些实用程序对不同的用户很有用。不是所有的实用程序都保存在/bin目录中。记住:UNIX实用程序有两种形式。一种是二进制(编译的)文件。这些实用程序运行速度快。另一种是shell脚本。这些也是可执行文件,但它们并不是编译好的形式或二进制形式。shell脚本在运行时执行,它们是一次性命令。因此从术语角度而言,它们被当作"解释性"的。Shell脚本不在/bin目录中。一些通用的二进制文件保存在/bin目录中,如图13-11所示。 现在深入学习这些内容。 ① /bin/ls /bin/ls是用于列出目录内容的实用程序。例如,如果在根目录中输入ls命令,由该命令得到的结果如图13-12所示,它对应于图13-11中根目录下的子目录。 HYPERLINK "http://images.51cto.com/files/uploadimg/20090702/135325402.jpg" \t "_blank"   图13-11  重要的UNIX目录/文件 HYPERLINK "http://images.51cto.com/files/uploadimg/20090702/135517694.jpg" \t "_blank"   图13-12  "ls"命令 几乎每个终端用户都会大量使用该实用程序。当在运行的UNIX系统中的命令解释器shell中提交该命令时,shell进程使用该系统调用定位对应该命令的二进制可执行文件。shell在/bin目录中找到该命令。/bin目录包括不同的符号名及其对应的索引节点。内核将"ls"作为符号文件名进行搜索。找到该文件之后,内核得到索引节点编号,并访问对应的索引节点。"ls"文件对应的索引节点包括磁盘块的地址,而这个地址正是存储"ls"二进制编译代码的位置。然后shell创建另一个进程(跳转执行该命令),将"ls"实用程序的二进制可执行代码加载到新创建的或分支生成的进程的地址空间中。现在这个新进程接管后续工作,并通过再次提交用于搜索根目录下不同目录的系统调用执行"ls"命令,然后显示这些目录名。 "ls"命令有多个选项,对这些选项的介绍超出了本书研究范围,这里不做任何介绍。 ② /bin/who /bin/who实用程序输出当前登录系统用户的相关信息。它报告出用户名、用户使用的终端、用户登录系统的日期和时间。示例命令及其输出结果如图13-13所示。 HYPERLINK "http://images.51cto.com/files/uploadimg/20090702/135658239.jpg" \t "_blank"   图13-13  "who"命令 UNIX在它的内部的数据结构中为每个用户保存了执行该命令需要用的这些细节信息。再次的,在本例中也要先定位"who"命令的二进制代码,然后加载,最后再执行该命令。 ③ 其他实用程序 /bin/mv是更改文件名的实用程序。它也可用于将文件移动到新目录中。旧文件及其名称不再存在于旧目录中。 /bin/cp将文件复制到新目录中。旧文件依旧保存在旧目录中。本例要创建新的物理文件。内核要分配新的磁盘块,然后为该文件创建新的索引节点。在旧目录(源目录)中保存的同时,目标目录现在给出了符号文件名以及对应该文件的新索引节点号。 (3) /UNIX /UNIX以可执行的二进制的形式包括UNIX内核真正的代码。当系统启动时,将/UNIX从磁盘读到内存中,然后开始启动系统。实际上,系统先读取/boot文件,接下来再读取/UNIX。 (4) /usr /usr是一个很重要的目录,所有用户都属于这个目录。默认情况下,所有的用户目录都是/usr目录的直接子目录,但对user-A、user-B、user-C等,用户可以组织另一个级别的目录(如图13-11所示的"users"目录)。每个目录下面可以包含一个目录层次。 除了用户目录之外,/usr还有3个主要的子目录--/usr/lib、/usr/bin和/usr/tmp。"lib"代表库,"bin"代表二进制,"tmp"代表临时文件。有趣的一点就是所有这些目录都在/usr目录中,当然也是根目录/.的直接目录。因此,有两个保存二进制文件的bin目录:/bin和/usr/bin。存在这两个目录没有任何原因。实际上,人们可以在/usr/bin或/bin存储所有的库文件。在SunOS操作系统中,这两个目录链接在一起,这意味着,从逻辑上讲,这两者只会被SunOS当作是一个目录。 /usr/lib目录存储如C、FORTRAN这类编程语言的库文件。 /tmp目录存储 stores 程序运行期间创建的暂时文件。例如,使用"ed"编辑文件时就会生成一个临时文件/tmp/e00512。这个临时文件保存了正在编辑的文件的副本,而不是对原始文件进行处理。当系统启动时,会自动清除/tmp目录。然而,如果用户在/tmp目录中使用如"e00512"这样的相同名称,就会有问题。为此,"ed"实用程序为创建的临时文件选择了一个奇怪而且不常用的名字,如"e00512"。 13.4.4  重要的UNIX目录/文件(2) (5) /lib /lib包括C编译器的主要内容,如/lib/cpp、C预处理器以及/lib/libc.a和C的子程序库。 (6) /etc 该目录包括各种用于管理系统的重要文件。其中一些列举如下。 (7) /etc/passwd 该文件包括登录系统时所需的基本信息。它包括对应每个用户的大量记录。每个用户的记录包括以下字段: username(用户名):这不需要做任何解释。 Password(密码):这是用户登录系统时必须提供的密码的加密形式。该字段可以是空的,但为安全起见,密码最好不为空。用户可以使用"passwd"命令更改自己的密码。 pw-age(密码寿命):这是一个改动密码有效时间的可选字段。该字段指明强制用户更改自己密码的时间。登录系统后,系统检查密码是否"到期"。如果密码到期,系统强制用户更改密码,系统提示用户输入新密码,接受新密码并在该文件的password字段中更新该密码。 userid(用户id):这是数字形式的id,对每个用户都是唯一的。 grouPid(组id):这是用户所属的group的id。 idstring(id字符串):这是完整的用户名。 homedir:这是用户登录系统后,自动放置用户的主目录。此时,将其复制到用户的u区。如前所述,这之后,用户可以很容易地从当前目录移动到其他目录或是列表等。当在系统中创建用户时,内核确认该用户的主目录,并由系统管理员将其与该用户的用户名、密码等一起输入,然后保存在/etc/passwd中。 command(命令):这是登录系统后,系统立刻执行的命令。典型地,这里指定要使用的如/bin/sh或/bin/csh的shell。登录系统后,内核搜索/etc/passwd文件,获取该命令,并调用该命令。这就是大多数时候用户登录系统后立刻看到shell提示符($)的原因。然后,特定用户可以按照自己的需求运行程序,例如登录系统之后可以立刻运行采购订单(PO)入口程序,这里用户需要指定该程序的路径名。这就是要做的全部工作。一旦用户登录系统,操作系统会立刻调用和启动PO入口程序。假定当天特定用户只使用特定屏幕,在航班、银行或零售业中就可以用到这个概念。这会节省大量的时间。 ② /etc/motd /etc/motd是包含用户登录系统时显示在终端上信息的文件。登录过程中的进程提取该信息,并显示该信息。系统管理员可以通过一个命令设置该消息。因此用户登录系统时可以看到如"Hello!Happy New Year!"这样的登录消息。 ③ /etc/fsck /etc/fsck包括一个检查文件系统一致性的实用程序。通常在系统引导阶段完成检查工作。这种不一致性是由断电或硬件故障引起的。该程序会检查目录、子目录以及文件的所有索引节点,从而确保不同目录和文件之间的链接是正确的,以及分配给不同块的彼此链接也是正确的。该程序还要对空闲块和坏块进行检查。为了进行检查,它要遍历多个条目。 ④ /etc/mount 如前所述,/etc/mount实用程序用于加挂文件系统。 ⑤ /etc/umount 如前所述,/etc/umount实用程序用于卸载文件系统。 ⑥ /etc/group /etc/group文件包括在任何UNIX安装中存在的所有组。任何文件都有3类用户:Owner(所有者)、Group(组)和Others(其他的)。可以为这几类分别授权不同的读(r)、写(w) 和执行(x)权限。例如,所有者可以有全部的"rwx"权限,组只有"r"和"x"权限,其他的只有"r"权限。/etc/group文件当作所有组的主文件。如果内核为任一文件创建或引用任一组,该组首先要存在于/etc/group这个主文件中,从而满足是一个有效的组。 ⑦ /tmp /tmp目录保存如编辑器这样的不同实用程序运行时产生的所有临时文件。 ⑧ /dev /dev目录包括不同的特殊设备文件。每个设备都有这样一个对应的文件。该文件包括设备驱动程序地址(直接地址/间接地址),以及不同参数。因此,当需要向设备写某些数据时,使用常用系统调用向文件"写"内容,除了这里的文件是对应该设备的特殊设备文件之外,没什么不同的。内核内部执行该系统调用的过程是通过合适的参数调用期望的设备驱动程序。这就是UNIX将这些设备当作文件的方式。 13.4.5  文件系统内部结构(1) 1. 综述 如前所示,一个磁盘可以分区从而包含多个文件系统。另外,使用mount(加挂)命令可以将一个文件系统扩展到多个物理磁盘上。从逻辑上讲,UNIX中的文件系统的布局结构如图13-14所示。读者可以认为文件系统分为4个不同的逻辑部分,如图所示。 文件系统中第一部分第0块预留给引导块。对文件系统而言,这涉及到引导过程,第一个块包括引导程序。机器加电之后,硬件自动读取包含引导程序的引导块。典型地,该引导程序包含一条读取较长引导程序的指令,或是读取UNIX内核的指令。即使磁盘上有多个文件系统,但也只有一个文件系统有这个引导块。在所有其他文件系统中,这个块是空的。 第二部分或第二个块被称作超级块。它充当文件系统头。它包括与文件系统相关的信息。任一文件系统在使用之前都要加挂到根目录上。当使用mount(加挂)命令时,文件系统的超级块被读到内核的内存中。因此,当UNIX开始运行的时候,对内核而言,所有文件系统的所有超级块在缓冲区内存中都是可用的。超级块不一定就是一个块的大小。通常它要比一个块大。"超级块"是个逻辑名称。   图13-14  文件系统的逻辑布局图 超级块包含的字段如表13-1所示。 表13-1  超级块的内容 ●       文件系统的大小 ●       文件系统中空闲块的数量 ●       空闲块的部分链表 ●       空闲链表中指向下一个空闲块的指针 ●       索引节点链表的大小 ●       系统中空闲索引节点的数量 ●       空闲索引节点的部分链表 ●       空闲链表中指向下一个空闲索引节点的指针 ●       锁定/标识符字段 本书通过以下内容阐述超级块中这些字段的重要性。 文件系统中可分配的块分为两部分:第3部分和第4部分,如图13-14所示。第3部分预留给索引节点。本书已经介绍过索引节点是定长记录,它存储文件的基本信息。它很像基本文件目录(Basic File Directory,BFD)条目。索引节点包含所有者、权限、定位分配给文件的数据块地址等信息。每个文件有且只有一个索引节点。然而,不是每个索引节点只对应一个文件。例如,如果两个符号名指向某个文件,也就是说如果这两个符号名之间存在链接,那么这两个符号名只有一个索引节点,即使它们的路径名不同,因此系统中有两个对应于该文件的不同符号名,该文件也只是有一个索引节点。由于UNIX把目录当作文件,所以每个目录也有一个索引节点,根目录也是如此。 文件系统有一些预留给索引节点条目的块。这就是限制该文件系统中文件、目录和子目录数量的原因。如果文件系统中有效文件/目录很少,又要新建文件,那么在文件系统的第3部分只有少量可分配的索引节点条目。如果用户要创建新的文件,文件系统中第3部分的所有其他条目都是空闲并且可分配的。用户总是会创建比较新的文件,同时删除一些老一点的文件。因此,文件系统第1部分中空闲索引节点条目的分配是一个动态过程。因此,内核必须维护文件系统第1部分中空闲索引节点条目列表,这样当用户新建文件时,内核就可以分配该列表中的条目,然后更新该列表。该列表可以很长。通常,内核会在超级块中预留一小块空间用于保存一些空闲索引节点条目。如果这个列表很小,那么在超级块中就可以保存它。如果比较大,内核就要在超级块外面存储剩余的条目。那么这些存储在超级块外剩余的条目就被称作磁盘索引节点。 在创建文件时,内核从超级块分配一个空闲索引节点。当超级块中的空闲索引节点用完之后,查询保存在超级块之外的空闲索引节点链表。从根本上讲,超级块在这种情况下充当了"缓存"。当超级块不再包含任何空闲索引节目条目时,就用磁盘索引节点中的条目更新它,同样也要对磁盘索引节点进行适当的更新。UNIX包含为新文件分配新索引节点或是如果删除文件,释放索引节点条目并将该索引节点添加到空闲列表的算法。 例如,参考图13-15可以看到本例中文件系统有26个(0~25)索引节点。该图给出了一些空闲的或是没有分配的索引节点。超级块包含空闲索引节点的部分链表,例如25、23、21、19、17、16、15和12。链表按照从高到低的顺序维护。超级块还维护指向文件系统中下一个空闲索引节点的索引或指针。该指针在图13-15中位于索引节点17处。无论何时当用户想要创建新文件时,发生以下情况: ① 内核访问超级块。如前所述,超级块从文件系统中的第二个块开始。因此,对内核而言,访问和读取该块没有任何问题。超级块包含一个指向下一个空闲索引节点的指针。现在内核可以访问该节点。 ② 内核将该索引节点分配给新文件。本例中该索引节点是17。 ③ 内核更新指向下一个条目的指针,也就是在分配索引节点17后,指针现在指向图13-15中的索引节点19。 ④ 当指针指明超级块中没有空闲的索引节点时,内核搜索磁盘索引节点从而找到空闲的索引节点,并更新超级块中空闲索引节点链表。同样内核还要更新指向超级块中链表最初位置的指针值,然后按照前面的步骤开始处理。   (点击查看大图)图13-15  空闲索引节点 文件系统中第4部分或可分配块的第二大部分包括可分配给不同文件的数据块,如图13-14所示。UNIX中并没有单元或簇的概念。按照需求,系统每次只能为文件分配一个块。分配给文件的块不必是连续的。因此,UNIX要保存分配给一个文件所有数据块的一个索引。在该文件的索引节点中可以有多个级别的索引以及数据块/索引的地址。因此,在访问文件的索引节点之后,系统就可以遍历文件的所有数据块。稍后在研究索引节点的结构中详细介绍这部分内容。 任何时候,某些数据块分配给某些文件,而其余的数据块空闲。UNIX有一个维护空闲数据块链表的有趣方式。在超级块自身中维护一个空闲数据块的部分链表。超级块还要维护一个保存在超级块中空闲数据块部分链表的指针。显然,超级块不能包含空闲数据块的全部链表。空闲数据块链表的其他条目分开保存。UNIX保存一个从超级块指向其他包含其余空闲数据块链表的块的指针。这很像保存空闲索引节点条目的方式。 13.4.5  文件系统内部结构(2) 2. 空闲块的分配 诚如前面介绍的,超级块保存一个空闲块的不完全链表。超级块要比一个数据块大。假定超级块自身包括一个1024字节的块,也就是包括256个4字节或32位的条目,每个条目对应磁盘上一个空闲块。显然,这是空闲块的不完全链表。图13-16表明超级块中编号为3、7、10、15、…、389的块空闲。该图还给出了指向最右端位置的"下一个空闲块"的指针,该指针指向编号为3的块。这表示当文件请求分配另一个块时,就可以将编号为3的块分配给它。 该链表被称作超级块缓存。如果文件请求块,内核就会从右向左检查超级块缓存以分配块。算法分配因此会很快。这个阶段,内核没必要遍历任何链表或指针。   (点击查看大图)图13-16  空闲块的分配 除了超级块中维护的空闲数据块链表之外,同样还要在超级块之外的磁盘上维护一些包含空闲块号的其他块。在超级块和这些块之间有链接,如图所示,这里加以简要介绍。由于编号为3、7、10等的块已经按照该顺序分配给不同的文件,所以内核还要更新超级块中指向"下一个空闲块"的指针。当分配超级块中最后一个块(也就是图13-16中编号为389的块)时,情况就不一样了。原因在于:对超级块中这个最后空闲块的分配约定完全不同。这个最后的空闲块实际上不是一个空闲块,实际上它包含接下来256个空闲块对应的256个条目。因此,当内核存取最后这个条目时,它会执行以下步骤: ① 访问并读取编号为389的块。 ② 将块389回写到超级块中空闲块链表上。现在,超级块缓冲中包括编号401、410…到797的空闲块。 ③ 初始化超级块中指向编号为401块的(也就是最右端的块)的"下一个空闲块"指针。 ④ 将编号为389的块当作空闲块使用,将其分配给请求的文件。 ⑤ 使用块389之后,内核对所有顺序请求的分配按照块号401、410…这个顺序进行,直到分配最后一个块(也就是块号为797的块)为止,分配结束。每分配一个块之后,内核更新超级块中指向"下一个空闲块"的指针。 ⑥ 重复上述过程,也就是读取编号为797的块,将其存储在内存中,先分配编号为797的块,然后将编号为797的块的内容写回到超级块上。 ⑦ 这会持续到所有块分配完为止。 如果文件删除一些记录,那么针对新添加的空闲块设计算法就很有意思。如果超级块可以在"空闲块列表"中放置该空闲块的块号,那么内核只要更新超级块就可以了。如果因为这个新条目的原因,超级块已经满了,那么就要将这个块的块号作为最后一个(也就是最左边的一个)维护,而且新空闲块的条目要放置在这个新分配的块中(类似于图13-16中的块号389)。该过程可以在不同层次进行。 人们比较关注该方法和用于空闲块分配的位映射法的比照情况。 15MB的磁盘需要60个大小为1KB的块,保存空闲块号。15MB的磁盘有15×1024=15 360个大小为1KB的块,因此,如果整个磁盘都没有分配,那么列表中就会有15 360个条目。大小为1KB的块可以保存256个条目。因此,为了保存空闲块号,就要有60个块,因为60×256=15 360。然而,位映射法占用15 360个位或1920字节,它比2个块还要少。相比UNIX使用的前一种方法,它占用的磁盘空间不到前者的1/30。UNIX使用该方法的优点是什么呢?主要优点就是:内核给文件分配块的速度更快。同样地,由于分配的磁盘块越来越多以及磁盘变满(也就是说,剩余的空闲磁盘块很少),这两种方法的差别也就很小了。 现在研究索引节点的结构,以及内核为文件分配空闲数据块的方法。 3. 索引节点的结构 索引节点包括以下信息: ① 所有者的用户id(uid) ② 所有者的组id (gid) ③ 保护位:诚如所知,UNIX将所有用户分成3类:所有者(Owner)、组(Group)和其他的(Others)。每一类要么有,要么没有读(r)、写(w)和执行(x)权限。因此,内核需要三个位为每类用户指明权限。因此在每个文件的索引节点中总共要用9位。 ④ 文件类型:指明文件是普通文件、目录、特殊文件还是FIFO文件。 ⑤ 文件访问时间:指明文件创建时间、最后一次使用该文件的时间以及最后一次改动该文件的时间。 ⑥ 该文件的链接数:指明文件已知的符号名个数。只有该数为0的时候,内核才会物理删除文件(释放所有数据块以及分配给该文件的索引节点)。显然,只有在所有用户从自己目录中删除该文件时才会出现这种情况。 ⑦ 文件大小 ⑧ 通过多个不同索引级别分配给该文件所有块的地址。图13-17给出了它们的结构。   (点击查看大图)图13-17  索引节点结构 UNIX有一个在索引节点中维护数据块地址的特殊方式,这其中还有一个原因:UNIX是在研发和教育环境中而不是商业环境中设计出来的。因此,它面向的环境已经不同。在这样的环境中,成百上千个学生创建小文件,然后忘了删除这些文件,通常一个人会有大量的小文件,而在商业环境中只有一些比较大的文件。这种情况如图13-18所示。 因此,UNIX想要为使用小文件的用户提供快速处理功能,与此同时对于那些使用大文件的用户也不会造成很大的不公平。UNIX采用的一种实现方式就是减少对小文件的地址转换(Address Translation,AT)时间。其实现如下(参见图13-17)。 索引节点预留一个保存13个块编号的位置。假定1024字节的磁盘块以及需要用4个字节(或32位)表示块号,那么系统要为每个索引节点预留13×4=52个字节。除了这13个块号之外,前10个是实际分配给文件的数据块的编号。因此,如果文件大小是1024×10=10 240个字节或者更少,那么分配给该文件的所有块号可以放在索引节点中。因此,内核可以在访问索引节点的时候立刻得到这些块号。编号从0到9的这10个块被当作是图13-16中的直接块。 13.4.5  文件系统内部结构(3) 当创建新文件时,最初所有10个条目都是空的。当向这些条目写某些内容并因此需要使用块时,如前所述,内核检查空闲的数据块链表,选择分配一个空闲数据块,并从空闲数据块列表中删除这个块的编号,在索引节点中插入这个块号。这个过程持续到文件中的前10个块分配完为止。分配块的时候,内核还要更新索引节点中的"文件大小"这个字段。通过执行一个简单的文件大小/块大小的算术操作,内核可以通过这个字段查找索引节点中的新条目,并在这个条目中插入新分配的块号。例如,如果文件大小是2048个字节,内核可以轻松地计算出,这也就是2048/1024=2个块,也就是10个块中只有两个块被填满。因此,下来就是第三个条目。   图13-18  针对文件的典型环境 如果文件大小超过10个块,会出现什么问题呢?如果发生这种情况,内核会从可用的空闲块中分配数据块,并将该块当作索引块。索引节点的第11个条目提供了该索引块的块号。如图13-17所示,索引块包含地址或者指针。这个索引块也有1024个字节,因此,它可以保存多于256个数据块号的256个条目(1024/4=256)。现在内核遍历空闲块链表,并将其中一个分配给该文件。现在内核将这个实际数据块的块号作为索引块中的第一个条目。随着文件的扩大,它重复这个获取新空闲数据块的过程,分配该数据块,并将该数据块的块号写到索引块中第2个条目,等等。内核通过前面介绍的使用文件大小的简单算术,计算出索引块中接下来要使用的条目。这个索引块被称作单级间接索引块。这是因为索引块直接指向数据块。如果已经分配10+256=266个块,也就是说,如果文件超过266×1024个字节,也就是266KB或0.266MB,那么内核就要使用双级间接索引块,如图13-17所示。 在两级索引中,索引节点中的第12个条目指向两个间接索引块。这个索引块也有256个条目,但不是直接指向256个数据块(像在单级间接索引中),而是指向间接寻址第二级的256个其他索引块。这里知道,每个索引块可以有256个块号。这就给UNIX提供了寻址10 + 256 + (256×256) = 65 802块或65.8 MB的能力。由此可以看到:内核可以通过三级间接地址,通过多极扩展可以寻址的全部块数是10 + 2561 + 2562 + 2563,这超过16GB的寻址空间。然而,如果索引节点中文件大小只有32位,那么由于这个原因,文件大小就局限在232 或4GB。 文件大小在地址转换中起着重要的作用。根据文件大小,内核知道是否要对索引节点自身中的块号(直接的)或是间接的特定级别的索引进行定位。 4. 地址转换 UNIX将文件当作字节流。假定应用程序提交一个写600字节新记录的系统调用。为了执行该系统调用,内核要经历以
/
本文档为【unix 文件系统】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索