当初上课上的迷迷糊糊,最近我查阅了一些资料,将文件系统中的基础知识有逻辑的整理出来。node
- 什么是文件?
- unix中的目录是什么?
- 如何理解硬连接和软连接?(文件共享)
- 目录中是如何检索文件的?
- 文件的逻辑结构和物理结构?或者说文件再磁盘上是如何被组织起来的?
- 空闲文件的组织与管理?
- 磁盘的组织与管理?
提到文件,大多数人的脑子中确定首先浮现的是pdf、jpg,mp3等文件。他们确实是文件,可是你脑子中所想的只是文件的文件体,也就是文件真正的数据(一些二进制流)所在。数据库
那么要对文件进行管理,只有这些数据不够,还须要一些描述信息(文件名、文件内部标识、文件存储地址、访问权限、访问时间),这些描述信息能够称为文件说明,也能够称为文件控制块(FCB)。windows
因此unix中的文件 = 文件体 + 文件描述信息。数据结构
下面思考一个问题:函数
XV6和全部的Unix文件系统都支持经过系统调用建立连接,给同一个文件指定多个名字。你能够经过调用link系统调用,为以前建立的文件“x/y”建立另外一个名字“x/z”。即便在windows中也能有建立快捷方式,将同一个文件重命名并存放在不一样的位置。而两个文件访问的内容确是如出一辙的。
因此,在文件系统内部,文件描述符必然与某个对象关联,而这个对象不依赖文件名。spa
那么这个对象就是你们熟知的inode(index node,索引结点)。inode是什么,直接拿inode的数据结构来看是最好不过的了。除此以外,系统会为每个inode分配一个惟一的编号。设计
inode的数据结构:unix
从上面能够知道,inode中存了文件体(也就是文件真实的数据)的地址,经过inode找到文件内容。这样一层封装,使得不一样的文件名均可以映射到这个inode上来,从而找到文件数据。指针
但是,文件名去哪了呢?inode中的内容很像上面讲的文件说明(文件描述信息),其实正是。不过偏偏缺了文件名。而文件名和inode编号之间必然有一个映射表,这张表又在哪里呢?答案就在目录!对象
目录就是一个文件。
一会儿可能没法理解,仍是从你的思想出发,提到目录你可能想到一个文件夹内部的结构。就大概这么一张图,也就是说目录内部应该包括一些文件(此处的文件指的就是通常的文件以下图中的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编号。
未完待续...