文件系统
文件系统存储文件属性、文件内容和目录。这些内容是怎样在文件系统中存储的呢?Linux将磁盘块分成了3部分。
其中,
- 超级块用来存储文件系统本身的信息。
- i-node节点表存放i-node节点,它存储了文件属性、所有者、权限等元数据信息
- 数据区分块存储文件数据,它是不连续存储的,一个文件的内容可能散落在数据区内部。
- 超级块
它是文件系统的第一个块。这个块存放文件系统结构信息,如每个区的大小,还记录这个磁盘块未使用空间信息。 - i-node节点表
每个文件的属性信息存放在这个表中,以i-node号为索引,所有i-node大小相同,是一个i-node数组,每个文件在都对应着唯一一个i-node号,即一个唯一的i-node节点。但是某个i-node节点可能对应多个文件名,这个后面提到。
只需要记住:表中每个节点按位置标识。 - 数据区
数据区存放文件实际内容。磁盘是按固定大小分块的,如果一个文件的大小超过了一个块的内容,那就为它分配多个块来存储。一个文件可能散落在好几百个磁盘块上,那么文件系统是如何跟踪这些块的呢?
文件和目录的工作过程
1. 创建文件的过程
文件有文件名、文件属性和文件内容。文件名存放在目录中,并与i-node号建立关联,文件属性存放在i-node中,文件内容存放在数据区。
因此,创建文件的四个主要操作如下:
- 存储文件属性:内核在i-node表中找一个空的i-node
- 存储文件数据:根据文件大小分配合适数量的空磁盘块,(Unix使用成组链接法管理空闲盘块
- 记录分配情况:在第1步的i-node节点上记录了第2步分配的磁盘序列
- 添加文件名到目录:以
<i-node_index, filename>
的形式在目录中建立文件名和实际的物理块号的关联。
2. 目录的工作过程
目录说白了就是包含了文件名的列表,按上面的理解,本质上就是有个包含i-node节点号和文件名的列表。
要查看文件名和i-node,只需要在 ls
命令加上 -i
选项
由上可知,所有从文件中读取数据的命令,例如
cat
, more
, who
等,以及高级接口调用,都是把文件名传给open
系统调用。内核首先根据文件名在目录中寻找文件名,进而知道这个文件名对应的i-node号,然后拿这个i-node号在i-node表中定位目标i-node,获取这个文件属性信息,内核这时候根据文件的权限位和执行者的UID判断是否有权限执行这个操作,如果没有,open
返回 -1,并设置全局变量errno
为EPERM
。如果权限允许,则根据i-node中保存的磁盘块序列到数据区按序读取文件内容。
一个问题:Linux如何跟踪大文件呢?
综合上面的讨论,我们知道,一个大的文件需要很多磁盘块,并且还知道i-node节点存放磁盘块的分配列表。问题就在于,固定大小的i-node如何存储大量,甚至超出节点范围的磁盘序列呢?
Unix/Linux的做法是:将磁盘分配列表的大部分存储在数据块,在i-node节点中存放指向那些块的指针
链接
1. 多重i-node和交叉链接
一个磁盘可以格式化为某一种类型的文件系统,一个文件系统自身是一棵独立目录树,而Linux允许多文件系统存在的原因是,它允许多个文件系统通过挂载
形成一棵目录树(其实是树的树)。
上图中,/dev/disk1s1 分区挂载在根目录/
上, devfs挂载在/dev
上。
注:分区是物理的,目录是逻辑的,分区必须挂载在具体目录上才能使用。
上面我们知道,一个磁盘中有i-node表,多个文件系统有多个i-node表。多棵树(文件系统)相互连接意味着一个i-node号并不唯一标识文件了,如不同文件系统的231号i-node指涉到不同的文件。
因此,Linux不允许从不同的文件系统生成指向同一文件的链接。
2. 符号链接
硬链接
是将目录链接到树的指针,同时也是将文件名和文件本身(i-node)链接的指针。硬链接不能指向其他系统的i-node,即不能跨系统链接。为了支持跨系统,Linux提供了软连接(符号链接)。顾名思义,符号链接通过文件名引用文件,而不是i-node。
如图所示,分别建立了a.txt 的硬链接 hardlink 和软链接 softlink ,检查发现,硬链接和源文件拥有同一个i-node号,而软链接与源文件的i-node不一样,softlink并不是原始文件a.txt, 但是读写它时,看起来跟原始文件一样。
Linux使用引用计数思想管理i-node,实际上一个文件名并不是实际的文件,只是一个指针,指向i-node,当i-node不再被指向,引用计数为0时,才实际删除文件数据。
硬链接按i-node引用文件的含义是:链接文件与原始文件引用同一个i-node,创建一个硬链接实际上增加一个到指定i-node的引用计数,删除某个硬链接只是减少一次计数,原始文件名仍指向该i-node,原始文件照常存在。
软链接按文件名引用的含义是:ln -s
生成的文件是原始文件名的一个符号链接,这个软链接文件的文件属性(修改时间,文件大小等)都不同于原始文件,正因为它不涉及原始文件的i-node,因此才支持跨系统和到目录的链接。在交叉设备链接情况下,如果保存原始文件的目录被删除了,或原始文件改名了,符号链接失效。
总而言之,硬链接按i-node引用文件, 软链接按文件名引用文件,硬链接类似于复制,软链接类似于快捷方式。
参考
《Unix/Linux编程实践教程》