670 likes | 878 Views
第 6 章 文件系统. 6.1 文件系统概述 6.2 文件管理 6.3 目录 6.4 逻辑文件系统 ——Ext2 6.5 虚拟文件系统 ——VFS 6.6 小结 习题. 数据处理是计算机的主要功能之一,与数据处理 相关的数据管理和数据保存是必不可少甚至是较为重 要的环节。在计算机中,大量的数据和信息是通过文 件存储和管理的。文件系统负责管理文件和逻辑文件 系统,提供管理设备、屏蔽设备复杂性的手段,为系 统内核其他部分、用户命令和系统函数调用提供统一 的服务接口。 本章主要讨论 Linux 系统中文件的概念、 目录结
E N D
第6章 文件系统 6.1 文件系统概述 6.2 文件管理 6.3 目录 6.4 逻辑文件系统——Ext2 6.5 虚拟文件系统——VFS 6.6 小结 习题
数据处理是计算机的主要功能之一,与数据处理数据处理是计算机的主要功能之一,与数据处理 相关的数据管理和数据保存是必不可少甚至是较为重 要的环节。在计算机中,大量的数据和信息是通过文 件存储和管理的。文件系统负责管理文件和逻辑文件 系统,提供管理设备、屏蔽设备复杂性的手段,为系 统内核其他部分、用户命令和系统函数调用提供统一 的服务接口。 本章主要讨论Linux系统中文件的概念、 目录结 构及访问权限,Linux的逻辑文件系统Ext2, 虚拟文 件系统VFS, 文件系统管理及缓冲区管理等内容。 管道(FIFO)文件是利用文件系统作为接口实现进 程间的通信,本章不再介绍,具体原理请参见 2.2.6 “进程通信”部分。
6.1 文件系统概述 通常我们把与管理文件有关的软件和数据,统称 为文件系统。它方便地组织管理计算机中的所有文 件,为用户提供文件的操作手段和存取控制。同时, 文件系统隐藏了系统中最为纷繁复杂的硬件设备特 征,为用户以及操作系统的其他子系统提供一个统 一、简洁的接口,通过文件系统,使得用户方便地使 用计算机的存储、输入/输出等设备。
在学习Linux进程管理时,我们也许注意到,系 统惟一感知和控制进程的关键数据——进程控制块 中,除了CPU和内存资源之外,只包含了文件系统 信息和文件信息,而没有设备的任何信息,这就是文 件系统所起的作用。 Linux系统中把CPU、内存之外 所有其他设备都抽象为文件来处理。进程只和文件系 统打交道,具体的细节,由设备管理部分具体实现并 为文件系统提供尽可能简洁统一的接口。因此,文件 系统还同时充当着设备管理接口的角色,用户进程使 用和操作具体的设备,都必须通过文件系统进行。文 件系统是操作系统中与管理文件有关的所有软件和数 据的集合。
不同的操作系统可能采用不同的文件系统。支持不同的操作系统可能采用不同的文件系统。支持 多种不同类型的文件系统是Linux操作系统的主要特 色之一。Linux系统自身的文件系称为ext2,它也是 Linux默认的文件系统。我们把ext2以及Linux支持的 文件系统称为逻辑文件系统, 通常每一种逻辑文件 系统服务于一种特定的操作系统,具有不同的组织结 构和文件操作函数,相互之间差别很大。Linux在传 统的逻辑文件系统的基础上,增加了一个称为虚拟文 件系统(VFS)的接口层,如图6.1所示。
系统中所有的设备,包括字符设备、块设备和网系统中所有的设备,包括字符设备、块设备和网 络设备,都按照某种方式由逻辑文件系统统一管理, 逻辑文件系统为它们提供访问接口。虚拟文件系统在 最上层,管理各种逻辑文件系统,屏蔽了它们之间的 差异,为用户命令、函数调用和内核其他部分提供访 问文件和设备的统一接口, 使得不同的逻辑文件系 统按照同样的模式呈现在使用者面前,对于普通用 户来讲,觉察不到逻辑文件系统之间的差异,可以使 用同样的命令来操作不同逻辑文件系统所管理的文 件,可以在它们之间自由地复制文件。
6.2 文件管理 6.2.1 文件 文件可以简单地理解为一段程序或数据的集合。 在操作系统中,文件被定义为一个命名的相关字符流 的集合,或者一个具有符号名的相关记录的集合。符 号名用来惟一地标识一个文件,也就是文件名。 Linux系统中,文件名最大长度由NR-NAME-LEN控 制,默认值为255个字符。 文件定义中所指出的不同基本组成单位表示了两 种形式的文件。相关字符流组成的文件是一种无结构 文件或流式文件。相关记录组成的文件称为记录式文 件。记录式文件通常主要用于信息管理。
在UNIX、Linux等操作系统中,把包括硬件设 备在内的能够进行流式字符操作的内容都定义为文 件。 Linux系统中文件的类型包括:普通文件,目录 文件,连接文件,管道(FIFO)文件、设备文件 (块设备、字符设备)和套接字。 Linux系统把文件按照其性质、用途等标准划分 为不同的类别。操作系统根据文件的类型处理文件。 按照用途,文件可以分为:系统文件、库文件和用户 文件。系统文件直接和操作系统本身有关,包括操作 系统核心和各种系统应用程序和数据;库文件通常指 系统提供给用户调用的各种标准过程、函数和应用程 序;用户文件是用户委托计算机文件系统管理的文 件。
当然,这只是一种相对的标准,对于Linux系 统,根据自己的实际需要,具有特殊权限的用户(系 统管理员)可以重新修改并编译升级整个内核,这个 过程将会修改大部分系统文件,同时库文件也可以按 照自己的需要添加和修改。 根据文件中数据的表示形式,可以把文件划分为 ASCII码文件和二进制文件。 按照文件操作过程中的保护级别,文件可以划分 为只读文件、读写文件、可执行文件,Linux操作系 统通过这样的方式来控制文件的访问权限。按照文件 中信息流向还可以把文件分为输入文件、输出文件和 输入/输出文件。按照文件在系统中的存在时间,可 以把文件分为临时文件和永久文件。
6.2.2 文件结构 系统使用者关心的只是如何方便地组织和使用文 件,即文件的逻辑结构,而系统的设计者则更关心文 件具体的实现方式,也即文件的物理结构。 1. 文件逻辑结构 文件的逻辑结构是用户可见结构,即从用户角度 观察到的文件系统。从逻辑结构来看,Linux系统的 文件采用的是字符流式的无结构文件。 用户通过对文件的存取访问来完成对文件的各种 操作,常用的访问方式包括顺序方式和随机方式。 Linux系统同时支持顺序和随机两种访问方式。
用户对文件的操作只能通过操作系统提供的命令接口用户对文件的操作只能通过操作系统提供的命令接口 或者函数调用接口。 2. 文件物理结构 文件的物理结构指的是文件在存储设备上的组织 方式,即一个文件在具体设备上的实现方法。外部存 储器也按照一定的规则划分为小的物理单元,称为 块,每个块大小相等,相应地,文件信息也划分为和 外存物理块相等大小的逻辑块。对于无结构文件来 讲,文件本身没有特定的逻辑结构,最小的单位是字 节,可以很方便地划分为逻辑块。
文件的物理结构通常解决文件的逻辑块与物理 块之间的映射关系,也即一个文件对应的物理块的 具体组织方式。常用的文件物理结构有顺序、串 联、索引和多重索引等方式。
(1) 顺序方式 顺序方式按照逻辑上的连续关系把文件依次存放 在连续的物理块中。如图6.2所示,文件逻辑块和物 理块之间是最简单的线性关系,因此很容易实现,也 可以相当方便地实现文件的顺序和随机访问,只要确 定了文件头的位置和文件长度,一切操作都可以快速 实现。但是,这些优势只有在文件能够一次性写入 的情况下才存在。由于文件建立时并不知道文件的长 度,系统无法确定该给这个文件分配多少个物理块。 而且,这种方式也容易造成磁盘碎片。
(2) 串联方式 串联方式的结构采用链表来实现,每一个物理块 分为两个部分,一部分用于存放数据,另一部分存放 一个指针,指向后续连接的下一个物理块。存放同一 个文件的物理块不需要连续,整个文件的连续性由链 表的指针来保证,如图6.3所示。这种方法几乎可以 利用每一个物理块,没有连续方式那样的碎片问题, 可以实现文件的动态增长,也可以在文件中任何一个 部位增加和删除内容。文件的顺序访问也可以方便地 实现,但是随机访问的实现变得很复杂。
(3) 索引方式 索引方式为每一个文件建立一张索引表,表中存 放文件的逻辑块与物理块之间的对应关系。也就是把 串联方式中每一个接点所记录的链表指针信息统一保 存在一个索引表中,如图6.4所示。这使得文件的非 连续存放、文件动态增长、方便的文件内部修改等串 联方式的优点都保留了下来,同时,也能够方便地实 现文件的随机访问。如果把整个索引表保存在内存 中,整个文件的访问效率也可以大幅度提高。这种方 案的问题在于索引表的处理。连续方式、链表方式、 索引方式都可以用来解决索引表的存放,比较好的方 案是索引方式。
实际中,很多操作系统采用一种称为多重索引的实际中,很多操作系统采用一种称为多重索引的 物理结构,同时使用单级索引和多级索引。每个文件 由一张索引表描述,表中一部分内容直接指向物理 块,称为直接块。索引表中同时还包含一部分二级索 引指针,指向新的索引表,类似的,文件索引表中还 可以包括三级甚至更高级的索引指针,提供更多的间 接块。对于比较小的文件,可以直接存放在一次间接 块提供的空间中,而对于较大的文件,才使用多次间 接块。这种方式的缺点一是索引表本身占用存储空 间,二是每次访问数据都需要先访问索引表,需要更 多的系统时间开销。只要索引表设计合理,能够保证
正常使用的大多数都只利用直接块,还可以把索引表正常使用的大多数都只利用直接块,还可以把索引表 放在内存中,保证系统的访问效率。 这种方式基本上保证了文件的动态可变,实现了 文件高效率地顺序和随机访问,Linux系统文件的物 理结构采用的就是多重索引方式,见图6.5。
6.2.3 Linux文件 Linux系统的文件是无结构的流式文件,文件的 物理结构采用易于扩展的多重索引方式,便于文件动 态增长,同时也可以方便地实现顺序和随机访问。基 于字节流的概念,Linux系统把目录、设备等都当作 文件来统一对待。Linux默认的是Ext2逻辑文件系 统。
Ext2文件系统中的所有文件都采用i节点(i- node)来描述,每一个文件、目录或者设备都对应 于一个且只能对应于一个i节点。每一个i节点包含两 个部分的基本参数:文件说明信息和索引表。根据所 存放的位置,i节点又可以分为磁盘i节点和内存i节 点,分别使用数据结构ext2-inode和ext2-inode-info来 描述。其中磁盘i节点静态存放在外部存储器,包含 了整个文件的完整说明信息和物理块分布情况,而内 存i节点是为了减少设备存取次数、提高文件访问效 率,在内存中特定区域中建立的磁盘i节点的映像。
磁盘i节点文件说明信息包括文件名称、类型、磁盘i节点文件说明信息包括文件名称、类型、 文件长度、所占用的物理块数、创建和最近一次访问 时间等基本信息,以及链接数、拥有者用户名、用户 组名以及存取控制表等与文件共享、保护和保密相关 的信息。每一个i节点的索引表前12个项记录文件直 接物理块的位置,后面3项分别是间接、二级间接和 三级间接物理块索引,这样的方式既可以保证小文件 能够快速存取,又可以适应大文件存储扩展的需要。 Ext2文件系统物理块的大小可以是1024、2048或者 4096字节,在初始化文件系统的时候由用户指定,默 认值是1KB,块地址占4字节,因此每个物理块可以
存放256个块的地址,这样,如果把一个i节点所有的存放256个块的地址,这样,如果把一个i节点所有的 物理块放满,得到最大的文件应该是: 直接块+间接块+二次间接块+三次间接块 即: 12KB+256KB+64MB+16GB 实际上,在32位PC上的Linux系统中,寻址范围 32位,文件最大最多只能达到4GB。 如果一个文件的内容小于等于12个块,物理块采 用默认值时是12KB,就可以全部使用直接块来存 放,能够保证相当高的存取效率。i节点具体结构可 以参看图6.5。 内存i节点除了包含磁盘i节点的说明信息之外, 还增加了当前文件打开状态信息。
6.3 目录 每一个文件系统都提供目录来记录文件的有关信 息,在包括Linux在内的很多操作系统中,目录本身 也是一种文件,可以按照文件进行管理,在Linux中 称为目录文件。利用目录的层次结构,可以对系统中 的文件方便地进行分隔管理,实现文件的快速搜索, 解决文件之间的命名冲突,同时也可以提供文件共享 的解决方案。
6.3.1 目录结构 最简单、最原始的结构是单级目录如图6.6(a) 。 这种结构实现简单,可以实现文件系统空间的自动管 理。但是,这样的结构中,用户必须保证每一个文件 的名称在整个系统中惟一。系统要访问某一个文件, 必须在整张目录表中搜索,效率也较低。一个直观的 扩展方式是采用两级目录结构,根目录下面可以存放 文件,也可以存放下一级目录(称为子目录),子目 录下面存放文件,如图6.6(b)。 进一步推广这种层次关系,就形成了多级目录结 构,每一级目录中都存放所属文件和下一级目录的信 息,整个目录层次结构形成一个完整的目录树。如图 6.6(c)。
树形的多级目录结构,可以更好地解决文件命名树形的多级目录结构,可以更好地解决文件命名 冲突问题。同时,文件系统用一个树状结构表示,根 据文件不同的类型、不同的拥有者以及不同的保护要 求,可以划分为不同子树,方便地实现文件的管理, 在这种树形层次结构中,文件的搜索速度也更快。几 乎所有的操作系统都采用树形的多级目录结构。
在树形的多级目录系统中,文件名由路径名给 出,路径名惟一确定一个文件在整个文件系统中的位 置,可以有两种方式来表示文件的路径。一种是绝对 路径名;另外一种方式是从当前目录开始,指定文件 相对于当前目录的位置。当前目录是指用户当前在目 录树中所处的目录位置,也称为工作目录。例如,在 Linux系统下有路径/home/dy/linux/kernel/sched.c, 路径的第一个字符是Linux系统的分隔符“/”,代表从 根目录开始,是一个绝对路径,这个路径表明在根目 录下有home目录,而home下又有dy子目录,一直到 最后的文件,文件的名称为sched.c。如果当前用户
的工作目录是/home/dy/linux/,这时相对路径 kernel/sched.c所指得就是文件 /home/dy/linux/kernel/sched.c。 和大多数支持多级目录的操作系统一样,Linux 系统每一个目录下面都有两个特殊的目录项“.”和 “..”,前者指当前目录,而后者指当前目录的上一级 目录。对于上面的例子,当前目录是 /home/dy/linux/,相对路径 ./kernel/sched.c和 kernel/sched.c具有相同的含义,而 ../指的就是 /home/dy,因此,../linux/kernel/sched.c也是指 /home/dy/linux/kernel/sched.c。
6.3.2 访问权限 对于普通文件、目录以及具体的设备,都存在一 个访问权限(也称为存取权限)控制问题。 文件存取权限即文件读、写和执行的许可权,它 和文件的共享、保护及保密相互联系、密不可分。 文件的共享是指不同的用户共同使用一个文件。 共享和由此带来的安全性问题是一对矛盾,每一个操 作系统都必须在二者之间找到一个平衡点。所谓安全 性,通常包括保护和保密两层含义。
1. 文件共享 文件共享指允许多个用户共同使用一个文件。文 件系统一般都提供文件共享方法,使得只要保存某个 文件的一个副本,就可以实现多个用户在不同目录下 共同访问这一副本。 系统中实现共享最简单的方法就是不同的用户使 用相同的绝对路径名来访问同一个文件,这种方法 中,所有用户使用同样的名称来访问共享文件。如图 6.7(a)所示,可以看出,这种方法的主要缺陷是需要 访问多级目录,多次访问外部存储器,效率低。
Linux等操作系统还提供了更为简洁的链接法来 实现共享。在需要访问共享文件的地方建立一个特殊 的链接文件,直接指向共享文件,链接文件和原共享 文件可以具有不同的名称,链接文件名也称为原共享 文件的别名,它们都指向相同的文件内容,访问链接 文件就是在访问共享文件本身。如图6. 7(b)所示。这 种方法具有更高的效率,但原本完整的树状文件系 统,经过链接之后变成了网状结构,一部分文件的路 径不惟一,也带来一定的管理开销,在Linux系统 中,链接文件作为一种单独的文件类型来对待。
2. 访问权限控制 文件的共享、保护和保密都涉及到文件访问许可 权限的问题,针对不同的需要,系统可以采用多种不 同的方式来控制文件的存取权限。 (1) 口令方式 在文件创建的时候,文件拥有者可以为每一个文 件设置访问口令(password),访问口令被记录在 文件说明信息中。文件系统在用户试图访问该文件的 时候,首先要求用户提供口令并与文件说明信息中记 录的口令进行比较,使用者必须提供正确的文件访问 口令才能够存取该文件。通过这样的方法,可以简单
地实现文件的共享与保密。口令验证的过程比较简地实现文件的共享与保密。口令验证的过程比较简 单,只是保密性能相对比较差。 (2) 密码方式 密码(encryption)在文件创建的时候,文件拥 有者在文件写入存储设备之前,通过特定的算法和加 密密钥对文件内容进行编码加密,而在读取文件的时 候,必须提供相应的解密密钥进行译码解密。加密和 解密可以采用相同或不同的密钥,只有确切知道解密 密钥的用户才能够读出被加密的文件。
口令方式中有时也采用一定的加密技术。加密 口令方式只是对口令本身加密,加密后的口令仍然 存放在文件说明信息中,而密码方式是对整个文件 进行加密,加密时采用的密钥掌握在用户自己手 中,因此,密码方式的保密性强,但是要耗费大量 的处理时间。
上面两种文件存取权限控制方法是针对特定文件上面两种文件存取权限控制方法是针对特定文件 的,在多用户系统中,还可以针对特定的用户进行文 件存取权限控制。大多数系统,包括Linux,用户身 份验证都采用用户口令方式,建立用户的时候,设置 其口令,口令以加密的形式存放在系统中,每次用户 登录都要提供口令,与系统中存放的数据进行比较, 如果相同,用户登录成功,否则,拒绝用户登录。在 这样的系统中,多个用户可能同时使用计算机,每个 用户都拥有自己的文件,这些文件的存取使用控制权 由用户拥有。
(3) 存取控制矩阵 存取控制矩阵是一个二维矩阵,其中一维是系统 中所有的用户,另一维是系统中所有的文件,矩阵的 每一个元素都表示该元素对应的用户对文件的存取控 制权限,如图6.8所示。当用户对某个文件进行操作 时,系统查找矩阵中该用户和该文件所对应的元素的 值,只有当该元素表明有访问许可时,才可以进行具 体的访问。
利用这样的矩阵,可以对系统中所有文件的存 取权限进行完整有效的控制。但是对于规模比较大 的系统,存储和管理这样的矩阵需要比较大的系统 开销。 用户对每一个文件的访问,都要对矩阵的一行 进行搜索,整体的效率比较低。
(4) 存取控制表 存取控制表是针对某个特定文件,把文件拥有者 和相关的用户按照某种关系划分为类,按照不同的用 户类赋予用户文件存取权限。Linux系统中,文件的 存取权限分别赋予文件拥有者、拥有者所在用户组和 其他用户组这三类用户,每一类访问的权限设置三 位,分别为读、写和执行,这样就相当于每个文件只 需要记录9位数据就可以进行权限控制了。 实际上,每一个文件的存取控制表都相当于是整 个存取控制矩阵中的一行元素。存取控制矩阵中的每 一行对应于一个文件,首先去掉空元素,然后把所有 的用户按照文件所有者、所有者所在组和其他用户组 简化之后,就可以得到该文件的存取控制表。
在Linux系统中,每一个文件都在文件说明信息 中保存着自己的文件存取控制表,只有符合存取控制 表中规定的条件,才允许进行具体的访问。 对设备文件的权限设置实际上是限制了用户对设 备本身的操作。 设置文件访问口令和文件加密属于文件级的访问 权限控制。在多用户系统中,必须要进行用户验证, 文件系统针对特定的用户,可以通过存取控制矩阵或 存取控制表来设置对文件的存取权限,这类方法可以 认为是基于用户身份的存取权限控制,属于用户级的 访问权限控制。
在这些控制方法中,不论是口令还是密钥,都可在这些控制方法中,不论是口令还是密钥,都可 以归结为口令。文件的存取控制是通过用户登录口令 来控制的,因此,文件的保护、保密,关键在于用户 口令的选取和保护。Linux系统中,文件的存取权限 可以通过特定的用户命令来修改,具体的控制方法, 参看本书第3部分相关内容。 实际上,计算机硬件故障、系统软件缺陷,都会 影响到文件的安全性,都可能涉及到文件的保护和保 密问题,这些内容不属于本书的讨论范围。
6.3.3 Linux目录分布 Linux系统中采用的是树形的多级目录结构。 只有在没有使用链接文件的情况下,整个文件系 统构成完整的目录树,每一个目录或者文件都有惟一 的绝对路径来确定。如果为了达到共享目的,建立链 接文件之后,目录树就由树状结构变成了网状结构, 被共享的文件内容可以通过不同的绝对路径来访问, 造成有些文件的绝对路径不惟一。
Linux系统根目录下通常有多个默认的子目录, 它们是bin实用程序子目录,存放大多数用户都可以 使用的常用系统工具;boot子目录,存放系统启动时 必须的内核映像等文件;dev设备子目录,系统在这 个子目录里为每个设备分配一个i节点;etc基本数据 子目录,存放系统的用户口令、网络配置等设置文 件,home用户数据子目录,默认情况下,每个用户 登录后的工作目录都设在这个目录下;lib系统函数 库子目录,存放着系统提供的动态和静态库函数; proc系统状态子目录,通过这个目录,可以动态地了 解系统内核的运行情况;root系统管理员的用户目
录;sbin系统管理实用程序子目录;另外还有tmp临录;sbin系统管理实用程序子目录;另外还有tmp临 时文件目录、usr用户软件子目录以及var记载系统运 行情况的日志子目录。 除了这些默认的子目录之外,系统管理员还可以 根据实际需要在根目录下建立新的子目录,比如专门 用来安装(mount)其他文件系统的特殊子目录等 等。一般用户,通常只能在自己的工作目录下或者其 他得到授权的目录下工作,根据需要建立合适的子目 录,安排自己的文件,未经授权,一般用户无法访问 其他人的用户目录及其中的文件。