Linux 文件系统相关的基本概念
本文介绍 Linux 文件系统相关的基本概念。
硬盘的物理组成
盘片
硬盘其实是由单个或多个圆形的盘片组成的,按照盘片能够容纳的数据量,分为单盘(一个硬盘里面只有一个盘片)或多盘(一个硬盘里面有多个盘片)的硬盘。下面是一张盘片的示意图(此图来自互联网):
磁道和柱面
硬盘中有磁头在盘片上读写数据,磁头固定在机械臂上,机械臂上有多个磁头(每个盘片的两侧各一个)。当磁头固定不动时(假设机械手臂不动),盘片转一圈所画出来的圆就是磁道(track)。所有盘片上相同半径的那个磁道就组成了柱面(cylinder)。柱面是磁盘分区是的最小单位。
扇区
由圆心向外画直线,可以将磁道再划分为扇区,扇区就是盘片上最小的读写单位。通常情况下,一个扇区的大小为 512 个字节。因此可以使用下面的公式计算磁盘的容量:
柱面数 * 磁头数 * 扇区数 * 512 字节
磁盘分区
为什么要对硬盘进行分区呢?
因为我们必须要告诉操作系统:这块硬盘可以访问的区域是从 A 柱面到 B 柱面。如此一来,操作系统才能控制硬盘磁头去 A-B 范围内的柱面上访问数据。如果没有告诉操作系统这些信息,它就无法在磁盘上存取数据。所以对磁盘分区的要点是:记录每一个分区的起始与结束柱面。
实际上,分区时指定的开始和结束位置是柱面上的扇区(sector):
下图是通过 fdisk 命令查看到的磁盘分区信息:
那么,这些分区的信息(起始柱面与结束柱面)被存放在了哪里呢?答案是磁盘的主引导区(Master Boot Recorder, MBR)。MBR 在一块硬盘的第 0 轨上,这也是计算机启动之后要去使用硬盘时必须读取的第一个区域。 这个区域内记录了硬盘里所有分区的信息即磁盘分区表,以及启动时可以写入引导程序的位置。因此 MBR 对于硬盘来说至关重要,如果它坏掉了,这块磁盘也就寿终正寝了。下面是磁盘分区表的示意图(此图来自互联网):
文件系统
在告知系统分区所在的起始与结束柱面后,需要将分区格式化为操作系统能够识别的文件系统。每个操作系统能够识别的文件系统并不相同,比如 Windows 系统在默认的情况下就无法识别 Linux 的文件系统,所以要针对操作系统来格式化分区。可以简单的认为每个分区就是一个文件系统。
逻辑块
不论哪种文件系统,目的都是为了存储数据。前面提到,硬盘的最小读写单位是扇区,而现实中数据的读写单位并不是扇区的大小,原因是使用扇区的大小为单位来读写数据的效率实在是太低了。因为一个扇区只有 512 个字节,而磁头是一个扇区一个扇区的读取数据,也就是说,如果文件有 10M,那么读取这个文件磁头就要进行 20480 次读取操作(I/O)。
为了提升效率,就有了逻辑块(Block)的概念。逻辑块是在分区进行文件系统的格式化时所指定的"最小存储单位",这个最小存储单位以扇区的大小为基础(因为扇区为硬盘的最小物理存储单位),大小为扇区大小的 2ⁿ 倍。此时,磁头一次可以读取一个逻辑块。指定逻辑块的大小为 4KB(即由连续的 8 个扇区构成的一个块),那么,同样读取一个 10M 的文件,磁头要读取的次数则大幅下降为 2560 次,这样就大大提高了文件的读取效率。
需要注意的是,逻辑块也并不是越大越好。因为一个逻辑块最多仅能容纳一个文件(这里指 Linux 的 ext2 文件系统)。这有什么问题呢?举例来说,假如逻辑块的大小为 4KB,有一个文件大小为 0.1KB,这个小文件将占用掉一个块的空间。也就是说,该块虽然可以容纳 4KB 的容量,然而由于文件只占用了 0.1KB,实际上剩下的 3.9KB 空间就不能再被使用了(完全浪费掉了)。所以好的方式是根据实际的使用场景来设置逻辑块的大小。
在分区上创建文件系统时,可以指定文件系统的逻辑块大小:
上面命令中我们指定的逻辑块大小为 1024 B,也就是两个扇区的大小。我们还可以通过 tune2fs 查看现有文件系统逻辑块的大小:
这里需要区分三个概念:
扇区、逻辑块和页
块设备中最小的寻址单元是扇区。
逻辑块是文件系统的一种抽象--只能基于块来访问文件系统。内核执行的所有磁盘操作都是按照块进行的(但是所有设备的 I/O 必须以扇区为单位进行操作)。对块的要求有:必须是扇区大小的 2 的整数倍;不能超过页的大小。
内核把内存的物理页作为内存的管理单位,因为从磁盘读取的数据最终都会被保存在内存中,所以系统优化的结果是不允许文件系统中的逻辑块超过内存页的大小。可以通过下面的命令查看系统中页的大小:
$ getconf PAGESIZE
超级块
分区完成后,每个分区会被格式化为一个文件系统。而每个文件系统开始位置的那个块就称为超级块(superblock)。超级块会记录整个文件系统的整体信息,包括 inode 与 block 的总量、使用量、剩余量等。
也就是说,要使用一个分区(或文件系统)来进行数据访问时,第一个要经过的就是超级块。所以,如果超级块损坏了,这个分区上的数据也就丢掉了。
inode
Linux 操作系统的文件数据除了文件实际内容外,通常含有非常多的属性,例如文件权限(rwx)与文件属性(拥有者、群组、时间参数等)。文件系统通常会将这两部份的数据分别存放在不同的区块,权限与属性放置到 inode 中,至于实际数据则放置到 datablock 区块中。
block
实际记录文件的内容,若文件太大时,会占用多个 block。
每个文件都会占用一个 inode,inode 内则有文件数据放置的 block 号码。下面是 inode、block 数据存取的示意图(此图来自互联网):
这种数据存取的方法我们称为索引式文件系统(indexed allocation)。
挂载点
在 Linux 系统中,文件系统被安装在一个特定的挂载点(一个普通的目录)上,所有的已安装文件系统都作为根文件系统树的枝叶出现在系统中。与这种单一、统一的树形成鲜明对照的就是 Windows 系统的表现,它们以字母命名文件系统,比如我们常见的 C 盘、D 盘。