Linux文件系统[apue]那些事儿,都有哪些细节我不懂?

摘要:本文尝试通过解释 api 接口底层做了什么来阐释 linux 文件系统在设计层面的一些考虑,配合通俗易懂的日常命令和简单程序来进行验证,践行“纸上得来终觉浅,绝知此事要躬行”的理念,目的是做一个 linux 文件系统的引入…
前言 说到 linux 的文件系统,好多人第一印象是 ext2/ext3/ext4 等具体的文件系统,本文不涉及这些,因为研究具体的文件系统难免会陷入细节,甚至拉大段的源码做分析,反而不能从宏观的角度把握文件系统要解决的问题。一个通用的 linux 文件系统都包含哪些概念?接口如何使用?设计层面需要考虑什么问题?这都在本文的讨论范围。当然了,内容都是从 apue 搬运过来的,经过了一点点梳理加工,原书还是基于比较老的 UFS (Unix File System) 进行说明的,有些东西可能已经过时了,不过原理层面的东西还是相通的,看过之后举一反三就好。 文件系统总览 开始详细说明之前,先看下文件系统的总体结构,对一些基本的概念有个大体印象。书上有个不错的图直接盗过来: 从图中可以看出,磁盘可以由多个分区组成,每个分区可以设置不同格式的文件系统。分区在 windows 上比较容易观察,就是常说的 C/D/E/F……这些,一块磁盘也可以只设置一个分区,不过一但系统重装时,用户数据就容易丢失,从这里可以看出,分区及其上的文件系统是可以跨操作系统存在的。把系统分区从 windows 重装成 linux,数据分区也能正常读取 (linux 也能识别 NTFS),说明文件系统是独立于操作系统的。 一个分区由多个柱面组成,柱面是多个盘片在同一个磁道上形成的存储面,这样设计是为了减少寻道时间提高性能。每个柱面存储了若干数据块与对应的 inode 节点,它们都是固定长度的。inode 可以看作是文件的元数据,存放了与文件的大部分关键信息,它们连续存放在一起形成 inode 表,这主要是为了提高读取大量文件信息的性能,另外也简化了 inode 的定位过程,直接使用下标就可以了,一般称之为 inode 编号。每个柱面还存放了 inode 位图与块位图,方便查找空闲的 inode 节点或数据块。 inode 存放的信息包括: 文件类型 文件长度 文件权限位 文件链接数 文件时间 文件数据块编号 设备号 …… 注意文件名是不存放在 inode 中的,文件名是变长的,最长的文件名 (255) 可能都要超过 inode 的固定长度了,不适合存储在 inode 中。文件是包含在目录中的,所以文件名与其对应的 inode 编号都存放在目录的数据块中,目录是一种特殊的文件,其数据块由系统维护,用户不能直接读写它的内容。 从上图可以看到,目录 inode -> 目录数据块 -> 文件 inode -> 文件/子目录数据块 形成了一个闭环,通过这样不断迭代可以读取到文件系统中的任意文件。 对于这个过程,可能有人会问了,inode 不是固定长度的吗,如何保存一个文件的所有数据块编号呢?这就涉及到数据块寻址了,当文件比较大的时候,光编号占用的空间就直接超过 inode 本身的长度了,所以不能直接存储在 inode 中,而要通过二级甚至三级寻址来查找全部的数据块,过程和内存的多级寻址有异曲同工之处,受主题限制就不深入展开了,感兴趣的读者可以参考文末链接。 inode 与数据块数量比例如何分配是另外一个问题,通常它们不是 1:1 的关系,这样当 inode 消耗光的时候,即使还有数据块,文件系统也不能创建新的文件了,这方面的案例可以参考这篇文章《[apue] Linux / Windows 系统上只能建立不超过 PATH_MAX / MAX_PATH 长度的路径吗? 》;但 inode 节点太多也会造成可观的容量损失,一般没有大量小文件的应用场景是不会将 inode 比例设置太多的。可以通过 df 来查看 inode 使用情况: $ df -i / Filesystem Inodes IUsed IFree IUse% Mounted on /dev/sda5 61022208 284790 60737418 1% / 这个比例可以在创建文件系统时指定,例如对于 mkfs.ext3 是通过 -i 参数指定: -i bytes-per-inode Specify the bytes/inode ratio. mke2fs creates an inode for ev‐ ery bytes-per-inode bytes of space on the disk. The larger the bytes-per-inode ratio, the fewer inodes will be created. This value generally shouldn't be smaller than the blocksize of the filesystem, since in that case more inodes would be made than can ever be used. Be warned that it is not possible to change this ratio on a filesystem after it is created, so be careful deciding the correct value for this parameter. Note that resiz‐ ing a filesystem changes the number of inodes to maintain this ratio. 关于这方面更多细节请参考文末链接。 文件权限 inode 存储了文件的权限设置,主要就是文件权限位。关于文件权限,这是另一个可以单独写一篇的话题了,请