共计 2857 个字符,预计需要花费 8 分钟才能阅读完成。
当初上课上的迷迷糊糊,最近我查阅了一些材料,将文件系统中的基础知识有逻辑的整理出来。
- 什么是文件?
- unix 中的目录是什么?
- 如何了解硬链接和软链接?(文件共享)
- 目录中是如何检索文件的?
- 文件的逻辑构造和物理构造?或者说文件再磁盘上是如何被组织起来的?
- 闲暇文件的组织与治理?
- 磁盘的组织与治理?
什么是文件?
提到文件,大多数人的脑子中必定首先浮现的是 pdf、jpg,mp3 等文件。他们的确是文件,然而你脑子中所想的只是文件的文件体,也就是文件真正的数据(一些二进制流)所在。
那么要对文件进行治理,只有这些数据不够,还须要一些形容信息(文件名、文件外部标识、文件存储地址、拜访权限、拜访工夫),这些形容信息能够称为文件阐明,也能够称为文件管制块(FCB)。
所以unix 中的文件 = 文件体 + 文件形容信息。
上面思考一个问题:
XV6 和所有的 Unix 文件系统都反对通过零碎调用创立链接,给同一个文件指定多个名字。你能够通过调用 link 零碎调用,为之前创立的文件“x/y”创立另一个名字“x/z”。即便在 windows 中也能有创立快捷方式,将同一个文件重命名并存放在不同的地位。而两个文件拜访的内容确是截然不同的。
所以,在文件系统外部,文件描述符必然与某个对象关联,而这个对象不依赖文件名。
那么这个对象就是大家熟知的 inode(index node,索引结点)。inode 是什么,间接拿 inode 的数据结构来看是最好不过的了。除此之外,零碎会为每一个 inode 调配一个惟一的编号。
inode 的数据结构:
- 通常来说它有一个 type 字段,表明 inode 是文件还是目录。
- nlink 字段,也就是 link 计数器,用来跟踪到底有多少文件名指向了以后的 inode。
- size 字段,表明了文件数据有多少个字节。
- 不同文件系统中的表达方式可能不一样,不过在 XV6 中接下来是一些 block 的编号,例如编号 0,编号 1,等等。XV6 的 inode 中总共有 12 个 block 编号。这些被称为 direct block number。这 12 个 block 编号指向了形成文件的前 12 个 block。举个例子,如果文件只有 2 个字节,那么只会有一个 block 编号 0,它蕴含的数字是磁盘上文件前 2 个字节的 block 的地位。
- 之后还有一个 indirect block number(当文件数据过于大的时候,用于扩大,此处咱们不具体探讨它)
从下面能够晓得,inode 中存了文件体(也就是文件实在的数据)的地址,通过 inode 找到文件内容。这样一层封装,使得不同的文件名都能够映射到这个 inode 上来,从而找到文件数据。
可是,文件名去哪了呢?inode 中的内容很像下面讲的文件阐明(文件形容信息),其实正是。不过恰好缺了文件名。而文件名和 inode 编号之间必然有一个映射表,这张表又在哪里呢?答案就在 目录!
unix 中的目录是什么?
目录就是一个文件。
一下子可能无奈了解,还是从你的思维登程,提到目录你可能想到一个文件夹外部的构造。就大略这么一张图,也就是说目录外部应该包含一些文件(此处的文件指的就是个别的文件如下图中的 mmap 文件)和子目录(下图中的存储管理、IO、基础知识都还是一个目录)。
接下来就好了解了,目录是一个文件,文件体(数据)中存的就是这些文件 / 子目录的 文件名 和 inode 编号的映射表!
也就是说,对于每个文件而言,其文件名和实在的数据是存储在不同的物理地位上的。
举个经典例子 , 通过门路查找文件的过程:/home/alex/main.py
/ 能够了解为根目录,根目录因为是固定的,所以其 inode 的地位是零碎已知的。那么先找到 root 的 inode 的编号(此处须要阐明能够通过 inode 编号间接计算出 inode 的地址,具体计算形式不在此赘述),读取其信息,其那些文件体的地址,而后找到文件体,发现外面都是文件名 / 子目录名与 inode 编号的映射关系,逐个遍历文件名(之后在检索中还有其余形式,此处为线性检索)而后找到匹配的“home”,查到它的 inode 编号,获取其 inode 中的内容,而后找到实在的数据。以此类推,找到 alex 目录文件的 inode 编号,继而再找到 main 文件的 inode 编号。此时,main 文件的 inode 中的指针指向的就是 main.py 实在的数据。
有一个十分乏味的景象,就是文件名是由其目录所存储的。而 root 文件没有上一级目录了,所以 root 是没有文件名,或者说是一个空的文件名,只用一个 / 示意。/home/alex/main.py 能够了解为空 /home/alex/main.py。
如何了解硬链接和软链接?
了解了 inode 概念,再来了解硬链接就不要太容易了!
硬链接理性的了解,就是为同一个 inode 取了一个新名字,这样新名字和旧名字对应的 inode 编号都是同一个文件。那么为什么要设计硬链接呢?当然是因为要共享咯!同时须要留神的是,在 inode 中有个属性叫做 nlink,当有一个新的硬链接时,inode 会将这个值加一,表明这个文件在被其他人共享。当删除这个硬链接时,inode 会判断 nlink 是否为 1,若为 1,则表明是这个文件最初一个客人要把我删除,那么在删除硬链接的同时,数据也会被删除;否则,间接将 nlink 减一即可。
硬链接存在的问题:文件的创建者不能删除文件。因为文件被共享之后,只有文件的最初一个所有者能力删除文件。
此处思考一个乏味的景象,是我本人的揣测。为什么不间接将所有的文件形容存在目录文件中呢?也就是说能不能让目录文件中的目录项为文件名与文件形容(原先 inode 中存储的信息)的映射呢?这样就不要先通过文件名找到 inode,再通过 inode 找到文件形容了。
考虑一下,如果此时呈现大量的硬链接,而且还是对同一个文件的,那么文件的文件形容就会被反复存储。(数据库中称之为传递依赖)那么将这些文件形容拆散进来,当做一个 inode 存储,在原表中搁置 inode 的编号。
引入软链接,能够解决上述的问题。软链接其实是存储了被共享文件的路径名,这个路径名能够是绝对路径也能够是相对路径。所以软链接的 inode 和被共享文件的 inode 不同,当通过软链接查找文件时,其实是先获取到被共享文件的路径名,而后循着这个门路查找文件。这样一来,若文件的创建者将文件删除,那么即便有着这个路径名也无奈查找到对应的文件。
同时,软链接也存在一些问题,就是每次都得通过门路逐层查找,开销较大。
目录中是如何检索文件的?
首先解答一个问题,就是 目录的构造是怎么的?咱们当初可能很好答复,应该是树状构造的。没错,然而目录构造最开始有单级目录构造、二级目录构造。再是树状构造,图状构造的。
单级目录构造就是将所有的目录项堆在一个表中。二级目录构造是依照用户分了一级进去,每个用户本人的目录项还是堆在一个表中。树状构造是对二级目录构造的推广,或者能够称之为多级目录构造。
检索文件的形式:线性表、哈希表。线性表之前曾经阐述过了,哈希表也就是散列存储,通过文件名间接输出到散列函数中即可失去 inode 编号。
未完待续 …