【篇首语】

自由并不是无拘无束任意妄为,而是在混乱之中创造秩序。

对于计算机的文件而言,其所遵守的秩序给我们带来了无比大的好处,让我们可以精确访问我们想要的文件,而且还能共享文件。操作系统的文件管理给我们很大的自由:可以读写执行文件,可以保护自己的文件,可以对文件分门别类,可以对文件创造链接,和别人共享文件。就无比庞大的互联网,也是基于文件的共享的,这样我们才能从此机访问彼机的网页。然后,我们不仅仅要享受这来自不易的自由,也要知道自由从何而来!

【混沌的开始】

计算机的硬盘里面,是一堆夹杂着的0,1。没有谁知道里面到底蕴含着什么信息,然而,人类将他们用一些规则把这些01组织成为文件,那么这片magic土地,生长出了无限的生命。然而,接着我们要这一切变得有序而且方便查找,我们知道内存是有序的,那么怎样用小小的内存去寻找大大的硬盘中的文件呢?这就像拿着一张地图,去找想去的地方。我们可以对硬盘进行分割了,成了一些扇区,而文件就存储在这些扇区里面,而怎样才能找到文件所在的确定的扇区呢?这就需要在内存中维护一张文件和硬盘地址的对应关系表,这张表里还维护了文件的许多信息。其中对于一个文件有一个数据结构抽象了它,我们叫做FCB(文件控制块,和进程控制块是一个原理),这个数据结构里面存储了文件的名字,类型,大小,创建日期,以及各种读写权限等信息。

有几种方法用来组织这张对应关系表,方便我们查找文件。

方法一:单级文件目录

将所有的文件统统罗列在一起,查找比较费时,而且不允许重名,不管是你的还是我的,都混在一起,不方便分享,不知道那个是你的哪个是我的。不利于插入和删除。

查找难度系数  N

 

方法二:两级文件目录

将各个用户的文件归到各自的目录下,从而更容易区分你我,也可以重名了。你有一个儿子叫小明,我有一个儿子叫小明,你家的是刘小明,我家的叫邓小明。而且查找比较容易了,你要找刘小明,你应该挨家挨户找,找到刘家,然后对刘家进行盘查,找到小明。相比叫所有人出来排好队(单级文件目录)一个个找少了很多工作。

查找难度系数 M + G    M 为分组数(多少人家),而G 表示某个分组的目录项(一家有多少口人)。

 

方法三:树形文件目录

树形文件目录用树数据结构来组织文件和目录。这就是我们可以在windows的资源管理器中看到的树形目录,一个目录下可能有很多子目录和一些叶子节点(即文件),这样其从属关系就十分明朗了。而且从根到叶子有且只有只有一条路径,可以通过这条绝对路径来查找文件,而且可以设置当前目录,用相对路径表示到另一个文件的走法,玩过linux的同学肯定知道cd . 和cd ..等命令吧,用的就是相对路径。当然,这样做有利也有弊端,利在于其在树中的路径是唯一的,可以解决重名问题,而且这个树形结果非常灵活,添加和删除文件或者目录,只需要改变一下树就可以了。比起单级文件要好得多,但是这样查找起来又不是很方便了,必须遍历这棵树,或者根据所给的路径去找文件,当目录层次比较多的时候,树的深度比较深,查找起来就比较耗费时间。但是总的来说,还是这个方法好,比较贴近于我们的思维和计算机的运算方式。

【如何查找】

有了存放目录和文件信息的结构,我们该如何查找需要的文件的信息呢?包括物理地址和文件名等属性。大致有两种方法,一种是线性检索法,一个个找,没什么好说的,就像遍历数组一样。另外一种是hash映射的办法,这种办法是用一个hash表达式计算目录到底放在哪里,这样可能算一下就能找到目录项所在,但是这种方法要避免冲突才是好的。

 

【文件共享问题】

如何找的自由已经解决了,接下来就是让文件自由交换的问题了。因为每个文件都有可能属于不同的主人,而主人有很多东西是不能给别人看或者用的(比如牙刷、再比如一个存了银行密码的文件),因为他们有不同的权限,而有些东西是需要共享的,比如团队在工作站中的代码。共享才是王道,为了共享,就很有必要让我可以轻松地访问你的文件,但是复制一份的成本太高了,所以如果能有个链接连到真正的文件会更划算。

方法一:

如果是在树形目录中,要加入链接,势必会破坏树的特性(根到叶子有且仅有一条路径),虽然共享文件有多个父目录了,但是这样会带来混乱。在书中加入链接之后,就成为了图,假如一个目录 dir 要包含 anotherDir 里面的  file.txt文件,那么就要将file.txt 作为一个目录项附加到dir下,但是这样这个文件只会出现在做了此操作的目录下,它记录的是一个另一个目录项,而不是直接的文件,而且其他用户不知道你增加了一个文件,所以不能通过第二个人共享这个文件。所以引入索引节点——存储了文件的物理地址信息的结构,它会记录有多少人共享了它,每在一个地方增加或者删除都能反馈到索引节点中。也就是说,这个文件被共享了,第二者都能看到你多了一个文件。但是这样会产生权限不清的问题,有ABC 三个用户,A授权B共享文件file.txt,当A不用了,就在A的目录中删除该项,然而它在磁盘中还是存在的,因为B还要用,而B又可能授权C 共享,这样文件的归属就很不明确了,是先属于A后属于B,还是一直属于B;而文件的归属决定谁对file.txt 具有管理权限,这是很重要的。

方法二:

符号链接:创建一种文件link(不是编译的那个东西,更像超链接),里面存储着另外一个文件file.exe的绝对地址,然后打开这个文件的时候,运行的却是file.exe.这就是我们经常看到的链接文件——快捷方式。我们的桌面的很多图标等带有小箭头的东西是一个快捷方式,它很小,但是很强大。这样就不用破坏文件的树结构,而只需要添加一条链接可以存储在目录项中,记录这个新的link文件的信息。但目录项中已经没有了直接链接到file.exe的目录项了。link就像我们的超链接一样,可以任意在世界的各个角落穿梭。这就像手持一个GPS,朝着目的地走就是了,不用理会那么多。

【文件的保护】

在上面的文件共享中说到,文件要有个权限记录,记录谁对它有什么样的权利。在linux中权限会有Read  Write Execue,对于每个身份(属于某个域),用它们来描述。

如果一个文件在751 ,它的各个域的权限如下:

第一位7: 文件创建者,拥有RWE 三项权限 111

第二位2:文件拥有者同组者,拥有R和E权限  101

第三位1:  其他人,拥有E权限 001

 

这样就有了一个秩序,不会搞不清等级。这样就能产生一个文件访问矩阵,例如下面的表

单独拿出一列来看,我们以文件为单位,记录各个用户对文件的访问权限 ——访问控制表(控制对文件而言)。

单独将一行抽取出来,我们以用户为单位,会有许多项文件的访问权限记录——访问权限表(权限对用户而已)。


而还有三种特殊的权力,可以修改这两张表和访问矩阵。

复制权     同一个文件的权限在不同用户之间复制。

所有权    可以增加或者删除一个文件不同用户的权限。

控制权     控制用户在一个用户中,修改对各种文件的访问权限,可以标志从一个域访问另一个域,方便了进程对文件的修改。

【小结】

操作系统的文件系统是相当复杂的,我们也获得了初步的自由,可以按我们的意愿访问文件,查看或者修改文件的权限等等,我们也知道实现的原理。当然这篇也只是惊鸿一瞥,拾人牙慧。真正要理解文件系统,还得亲手去写才能体会,笔者就十分迫切地动手以加深理解。文件系统最核心的部分还是在于文件的目录表,它决定我们查找的方式,也就决定我们查找的效率。另外,推荐一个软件 everything,其查找文件相当快,是技术人必备软件,其速度之快,难以想象。当然它肯定是对文件建立目录,然后迅速查找它建立的目录,而系统自带的查找工具则逊色很多,有兴趣可以研究其目录表和查找算法。

by bibodeng      2012-04-24          原载于http://bibodeng.web-149.com/