笔者在前文《Linux EXT2 文件系统中 <https://www.cnblogs.com/sparkdev/p/11212734.html>》中介绍了
EXT2 文件系统中的基本概念,本文继续以 EXT2 文件系统为例介绍文件系统是如何管理文件存储的。

inode

在前文介绍文件系统时我们提到了 inode 和 data block。在 EXT2 文件系统中,inode 用来存放文件的元信息,data block
用来存放文件的内容。inode 包含的文件元信息有:

* 该文件的读写权限(rwx)
* 该文件的拥有者和所属组(owner/group)
* 该文件的大小
* 该文件的 ctime(创建时间)
* 该文件的 atime(最近一次的读取时间)
* 该文件的 mtime(最近修改的时间)
* 该文件的特殊标识,比如 SetUID 等
* 该文件真正内容的指向(文件 data block 的位置)
总之,除了文件名之外的所有文件信息都存在 inode 中。我们可以使用 stat 命令来查看文件的 inode 信息:
$ stat test.txt


inode 的大小
inode 本身是会消耗磁盘空间的,我们可以通过下面的方式查看 inode 的大小:
$ sudo dumpe2fs -h /dev/sdd1 | grep "Inode size"
在笔者的机器上,输出的结果如下:
dumpe2fs 1.42.13 (17-May-2015) Inode size: 256
也就是说一个 inode 占用 256 个字节的磁盘空间。

inode 耗尽问题
因为每个文件需要占用一个 inode,所以生产中会碰到 inode 耗尽导致无法创建新文件的问题。我们可以通过 df 命令 的 -i 选项查看文件系统中
inode 的使用情况:
$ df -i


文件

每个文件都会占用一个 inode,inode 内则有文件数据放置的 block 号码。当我们在 Linux 下的 ext2
文件系统中创建一个一般文件时,ext2 文件系统会分配一个 inode 与相对于该文件大小的 data block(一个或多个) 给该文件。inode
记录该文件的权限与属性,并记录分配到的 data block 号码。例如:假设一个 data block 的大小为 4 KBytes,而要创建一个 100
Kbytes 的文件,linux 就会分配一个 inode 与 25 个data block 来储存该文件!
单个文件,inode 和 data block 的示意图(可以简单的理解为下图的样子):



这种数据存取的方法我们称为索引式文件系统(indexed allocation)。

虽然从实现的层面上来看,可以直接从 inode 找到其对应的 data block,但是我们却不能通过 inode
直接访问文件,因为这会破坏通过权限进行的访问控制。例如,如果没有遍历目录的权限,那么无论文件上的权限是什么,都不能访问该目录中的任何文件。如果可以通过inode访问文件,就可以绕过目录权限。

目录

注意,inode 本身并不记录文件名,文件名的记录是在目录的 data block 当中。
目录本质上也是一个文件,所以当我们在 ext2 文件系统中创建一个目录时,文件系统会分配一个 inode 和至少一块 data block
给这个目录。其中,inode 记录该目录相关的权限与属性,并记录分配到的 data block 号码。而 data block
中则记录着在这个目录下的文件名(目录也是文件)与该文件名的 inode 号码。也就是说目录所占用的 data block 的内容记录着类似下面的信息:



目录项
文件名及其对应的 inode 被称为目录项。其实,目录项是内存中的数据结构,所以实际情况是文件名对应的是指向 inode
的指针。我们可以通过下面的示意图来理解 inode、目录、文件以及目录项之间的关系:



从磁盘读取一个文件的过程

由于目录树是由根目录开始读起,因此通过文件系统的挂载信息可以找到挂载点的 inode 号,此时就能够得到根目录的 inode 内容,并通过这个 inode
读取根目录的 data block 中的文件名称,再一层一层的往下查找,直到读到正确的文件名。下面让我们通过读取 /etc/passwd
文件来理解文件的读取过程。



上面的 ls 命令使用 i 选项输出了 /、 /etc、 /etc/passwd 的 inode 分别为 2、4325377、4329700。
我们通过当前用户 nick 读取 /etc/passwd 文件的内容,其过程如下:

* / 的 inode 号为 2,权限信息允许我们读取 data block 中的内容(有 r 与 x)
* / 的 data block 中记录的 etc/ 目录的 inode 号为 4325377
* etc/ 的 inode 中权限信息包含 rx,因此用户 nick 可以读取 etc/ data block 的内容
* etc/ 的 data block 中记录的 passwd 文件的 inode 号为 4329700
* 文件 passwd 的 inode 中权限信息包含 r,因此用户 nick 可以读取 passwd data block 的内容
* passwd 的 data block 中的内容被读取出来
参考:
鸟哥的私房菜
理解inode <http://www.ruanyifeng.com/blog/2011/12/inode.html>
Linux inode 详解 <https://blog.51cto.com/tengq/1878165>
关于 inode
<https://www.ibm.com/developerworks/cn/aix/library/au-speakingunix14/index.html>
目录项对象 <http://guojing.me/linux-kernel-architecture/posts/dentry-object/>

友情链接
ioDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信