您的位置:首页 > 其它

操作系统 — 文件系统

2018-01-14 16:25 190 查看

文件系统

在unix文件系统是unix系统的心脏部分,提供了层次结构的目录和文件.文件系统将磁盘空间划分为每1024个字节为一组,称为块(也有用512字节)

为一块的.编号从0到整个磁盘空间的最大块数.

在unix当中,之前我们在文件描述符 文件表项 v节点表项符当中多次提到了i节点,但是我们想了解i节点就必须了解磁盘空间当中的文件系统,所

以我们来介绍unix文件系统的基本结构. 同时了解i节点和指向i节点的目录之间的区别是非常重要的. 我们可以把一个磁盘分为一个或多个分区,

每个分区可以包含一个文件系统. i节点是固定长度的记录项,它包括有关文件的大部分信息.



我们可以看到图上每个分区都是一个文件系统,其实在磁盘当中分的更细,分区中每个柱面其实都是一个小的文件系统,这里的文件系统分为:

>超级块: 文件系统当中的第一块被称为超级块,这个块存放文件系统本身的结构信息,比如每个区域的大小,未被使用的磁盘块的信息.

>i节点: 超级块的下一部分就是i节点表,文件系统中的每一个文件都在该表中都对应一个i节点. i节点是固定长度的记录项,它包含有关文件的

大部分信息. Linux文件系统使用 索引节点i 来记录文件信息,索引节点是一个结构,用固定长度. 它包含了一个文件的长度,创建以及修改时间

,权限,所述关系,找到磁盘存储位置的指针等等信息.

>数据区: 文件的内容保存在这个区域中,磁盘上所有块的大小都相同,如果文件所包含了超过一个快的内容,则文件内容存放在多个磁盘块中,

并把磁盘块的分配情况记录在文件的i节点中的磁盘序列表中.

一个文件系统当中分有许许多多的柱面题,如果我们仔细观察每一个柱面题当中的i节点和数据库部分,那么它的结构就是下图这样的结构:



记住unix/Linux下一切皆文件,目录也是文件! 我们来分析这个结构: 每一个目录块和数据块都有自己唯一指定的i节点. 但是一个i节点可能接受

多个文件或者多个目录(同一个i节点不可能有文件和目录共同指向). 所以一个i节点里面存储关于自己对应文件或者目录的相应信息.你只需要知道

你的i节点编号就能找到相应的文件信息.一个i节点只能存储一个文件或者目录的信息. 并且不能多个目录公用一个i节点,因为这样可能会导致环

形链接,导致文件遍历出错. 还有一个问题,看下图:



在图中有两个目录块当中的文件指向同一个i节点.每一个i节点中都有一个链接计数,其值是指向该i节点的目录项数(或者文件计数).只有当链接计

数减少至0时,才可删除文件. 这就是为什么"解除对一个文件的链接"操作并不总是意味着"释放该文件占用的磁盘块"的原因.这也是为什么删除一

个目录项的函数被称之为unlink而不是delete的原因.  在stat结构中,链接计数包含在st_nlink成员中,其基本系统数据类型为nlink_t,这种链

接类型称为硬链. 其中POSIX.1常量LINK_MAX指定了一个文件链接数的最大值.

另一种链接类型称为符号链接,符号链接文件的实际内容包含了该符号链接所指向的文件的名字. 在下面的例子中,目录项中的文件名是三个字符

字符串lib,而在该文件中包含了7个字节的数据user/lib:

1rwxrwxrwx   1  root  7 sep 25 07:14 lib->urs/lib
该i节点中的文件类型是S_IFLNK,于是系统知道这是一个符号链接(软连接).

i节点中包含了文件有关的所有信息:文件类型,文件访问权限位,文件长度和指向文件数据块的指针等. stat结构中的大多数信息都是取自i节点。

只有两项重要数据存放在目录项中:文件名和i节点编号.i节点编号的数据类型是ino_t.

因为目录项中的i节点编号指向同一文件系统中的相应i节点,一个目录项不能指向另外一个文件系统的i节点. 这也就是为什么in命令,不能跨越文

件系统的原因. 我们说明了普通文件的链接计数概念,但是对于目录文件的链接计数字段又如何呢? 假定我们再工作目录中构造了一个新目录:

$mkdir testdir



我们现在观察这个图,该图显式的显示出了.(当前目录)和..(上层目录)项. 编号2549的i节点,其类型字段表示它是一个目录,链接计数为2.任

何一个叶目录的链接的链接计数总为2,数值2来自于命名该目录(testdir)的目录项以及该目录的.项. 编号为1267的i节点,我们就叫他hehedir,其

类型字段表示它是一个目录,链接计数大于或等于3. 它大于或等于3的原因是,至少有三个目录项指向他. 第一个是命名hehedir的目录,这个很容

易理解,当你创建了testdir之后,hehedir就会有一项链接testdir,同理创建hehedir的上层目录肯定也会链接hehedir的.第二个是在该目录中的.

项,第三个是在其子目录testdir中的..项. 注意,在父目录中的每一个子目录都使该父目录的链接计数增加1.如上所述,任何一个文件可以有多

个目录项指向其i节点. 创建一个指向现有文件的链接的方法是使用link函数或者linkat函数.

int link(const char* oldpath,const char* newpath);
int linkat(int efd,const char *oldpath,int nfd,const char* newpath,int flag);
两个都是成功返回0,出错返回-1. 创建新目录项和增加链接计数应该是一个原子操作的 虽然POSIX.1允许实现支持跨越文件系统的链接,但是大多

数实现要求现有的和新建的两个路径名在同一个文件系统中.如果实现支持创建指向一个目录的硬链接,那么也极限于超级用户.其理由是这样做可

能会在文件系统中形成循环.大多数处理文件系统的实用程序,大多数处理文件系统的实用程序都不能出路这种情况. 因此很多文件系统不允许对目

录的硬链接. 为了删除一个现有的目录项,可以调用unlink函数.

int unlink(const char* pathname);
int unlinkat(int fd,const char* pathname,int flag)
这两个函数会删除目录项,并且将由pathname所引用文件的链接计数减一. 如果对该文件还有其他链接,则仍可通过其他链接访问该文件的数据.

如果出错对文件不进行任何更改. 我们前面已经提到过,为了解除对文件的链接,必须对包含该目录项的目录具有写和执行权限. 如果对该目录设

置了粘着位,则对该目录必须拥有写权限,并且具备下面三个条件之一:

1.拥有该文件

2.拥有该目录

3.具有超级用户.

只有当链接计数为0的时候,该文件内容才可以被删除. 还有就是当一个进程打开这个文件,其内容也不能删除. 关闭一个文件时,内核首先检查打

开该文件的进程个数; 如果这个技术达到0,内核再去检查其链接计数; 如果链接计数也为0,那么就删除该文件的内容.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: