文件系统基础知识,看这一篇就够了!

当初上课上的迷迷糊糊,最近我查阅了一些资料,将文件系统中的基础知识有逻辑的整理出来。node

  1. 什么是文件?
  2. unix中的目录是什么?
  3. 如何理解硬连接和软连接?(文件共享)
  4. 目录中是如何检索文件的?
  5. 文件的逻辑结构和物理结构?或者说文件再磁盘上是如何被组织起来的?
  6. 空闲文件的组织与管理?
  7. 磁盘的组织与管理?

什么是文件?

提到文件,大多数人的脑子中确定首先浮现的是pdf、jpg,mp3等文件。他们确实是文件,可是你脑子中所想的只是文件的文件体,也就是文件真正的数据(一些二进制流)所在。数据库

那么要对文件进行管理,只有这些数据不够,还须要一些描述信息(文件名、文件内部标识、文件存储地址、访问权限、访问时间),这些描述信息能够称为文件说明,也能够称为文件控制块(FCB)。windows

因此unix中的文件 = 文件体 + 文件描述信息数据结构

下面思考一个问题:函数

XV6和全部的Unix文件系统都支持经过系统调用建立连接,给同一个文件指定多个名字。你能够经过调用link系统调用,为以前建立的文件“x/y”建立另外一个名字“x/z”。即便在windows中也能有建立快捷方式,将同一个文件重命名并存放在不一样的位置。而两个文件访问的内容确是如出一辙的。

因此,在文件系统内部,文件描述符必然与某个对象关联,而这个对象不依赖文件名spa

那么这个对象就是你们熟知的inode(index node,索引结点)。inode是什么,直接拿inode的数据结构来看是最好不过的了。除此以外,系统会为每个inode分配一个惟一的编号设计

inode的数据结构:unix

  • 一般来讲它有一个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编号。

未完待续...

相关文章
相关标签/搜索