首页 > 技术文章 > 19文件存储结构

rock-cc 2018-06-27 11:16 原文

Linux 文件存储结构

1. 根目录“/”

在Linux系统文件中,目录、字符设备、块设备、套接字、打印机等都被抽象成了文件,即“Linux系统中一切皆文件”。Linux系统中的一切文件都是从“根(/)”目录开始的,并按照文件层次化标准(FHS)采用树形结构来存放文件,以及定义常见目录的用途。另外,Linux系统中的文件和目录名称是严格区分大小写的,并且文件名称中不得包含斜杠(/)。
image

前文提到的 FHS 是根据以往无数Linux系统用户和开发者的经验而总结出来的,是用户在Linux系统中存储文件时需要遵守的规则,用于指导我们应该把文件保存到什么位置,以及告诉用户应该在何处找到所需的文件。

但是, FHS 对用户来说只能算是一种道德上的约束,有些用户就是懒得遵守,依然会把文件到处乱放。在Linux 系统中,最常见的目录以及所对应的存放内容如下:

/boot				开机所需要文件 ———— 内核、开机菜单以及所需配置文件等			
/dev				以文件形式存放任何设备与 接口
/etc				配置文件
/home				用户家目录
/bin				存放单用户模式下还可以操作的命令
/lib				开机时用到的函数库,以及/bin与/sbin下面的命令要调用的函数
/sbin				开机过程中需要的命令
/media				用于挂载设备文件的目录
/opt				放置第三方的软件
/root				系统管理员的家目录
/srv				一些网络服务的数据文件目录
/tmp				任何人均可使用的“共享”临时目录
/proc				虚拟文件系统,例如系统内核、进程、外部设备以及网络状态等
/usr/local			用户自行安装的软件
/usr/sbin			Linux 系统开机时不会使用到的软件/命令/脚本
/usr/share			帮助与说明文件,也可放置共享文件
/var				主要存放经常变化的文件,如日志
/lost+fond			当文件系统发生错误时,将一些丢失的文件片段存放在这里
2. 物理设备的命名规则

在 Linux 系统中一切都是文件,硬件设备也不例外。既然是文件,就必须有文件名称。系统内核中的 udev 设备管理器会自动把硬件名称规范 起来,目的是让用户通过设备文件的名字可以猜出设备大致的属性以及分区信息等;这对于陌生的设备来说特别方便。另外, udev 设备管理器的服务会一直以守护进程的形式运行并侦听内核发出的信号来管理 /dev 目录下的设备文件。Linux 系统中常见的硬件设备的文件名称如下:

IDE 设备							/dev/hd[a-d]
SCSI/SATA/U 盘					/dev/sd[a-p]
软驱								/dev/fd[0-1]
打印机								/dev/lp[0-15]
光驱								/dev/cdrom
鼠标								/dev/mouse
磁带机								/dev/st0 或 /dev/ht0

由于现在的 IDE 设备已经很少见了,所以一般的硬盘设备都会是以“dev/sd” 开头的。而一台主机上可以有多块硬盘,因此系统采用 a~p 来代表 16 块不同的硬盘 (默认从 a 开始分配),而且硬盘的分区编号也很讲究:

主分区或者扩展分区的编号从 1 开始,到 4 结束;
逻辑分区从编号 5 开始;

设备文件名“/dev/sda5”的含义:

首先,/dev/目录中保存的应当是硬件设备文件;
其次,sd表示是存储设备;
然后,a表示系统中同类接口中第一个被识别到的设备;
最后,5表示这个设备是一个逻辑分区;

一言以蔽之,“/dev/sda5”表示的就是“这是系统中第一块被识别到的硬件设备中分区编号为5的逻辑分区的设备文件”。

3. 主分区、扩展分区和逻辑分区

正是因为计算机有了硬件设备,我们才可以在玩游戏的过程中或游戏通关之后随时存档,而不用每次重头开始。硬盘设备是由大量的扇区组成的,每个扇区的容量为 512 字节。其中第一个扇区最重要,它里面保存着主引导与分区表信息。

就第一个扇区来讲,主引导记录需要占用 446 字节,分区表为 64 字节,结束符占用 2 字节;其中分区表中每记录一个分区信息就需要 16 个字节,这样一来最多只有4个分区信息可以写到第一扇区中,这4个分区信息可以写到第一个扇区中,这4个分区就是4个主分区。第一个扇区中的数据信息如下:
image

那么,问题来了 —— 第一个扇区最多只能创造出 4 个分区?于是为了解决分区个数不够的问题,可以将第一个扇区的分区表中 16 字节(原本要写入主分区信息)的空间(称之为扩展分区)拿出来指向另一个分区。也就是说,扩展分区其实并不是一个正真的分区,而更像是一个占用 16 字节分区表空间的指针 —— 一个指向另外一个分区的指针。这样一来,用户一般会选择使用 3 个主分区加 1 个扩展分区的方法,然后在扩展分区中创建出数个逻辑分区,从而来满足多分区(大于 4 个)的需求。

所以说,主分区不能超过 4 个,如下图所示。

image

所谓扩展分区,严格地讲它不是一个实际意义的分区,它仅仅是一个指向下一个分区的指针,这种指针结构将形成一个单项链表。

4. 文件系统

用户在硬件存储设备中执行的文件建立、写入、读取、修改、转存与控制等操作都是依靠文件系统来完成的。文件系统的作用是合理规划硬盘,以保证用户正常的使用需求。Linux 系统支持数十种的文件系统,而最常见的文件系统如下:

Ext3 —— 是一款日志文件系统,能够在系统异常宕机时避免文件系统资料丢失,并能自动修复数据的不一致与错误。然而,当硬盘容量较大时,所需的修复时间也会很长,而且也不能百分之百保证资料不会丢失。它会把整个磁盘的每个写入动作的细节都记录下来,以便在发生异常宕机后能回溯追踪到被中断的部分,然后尝试进行修复。
Ext4 —— Ext3的改进版本,作为 RHEL6 系统中默认文件管理系统,它支持的存储容量 高达 1EB( 1EB=1,073,741,824GB),且能够有无限多的子目录。另外,Ext4 文件系统能够批量分配block块,从而极大地提高了读写效率。
XFS —— 是一种高性能的日志文件系统,而且是 RHEL7 中默认的文件管理系统,它的优势发生意外宕机后尤其明显,即可以快速地恢复可能被破坏的文件,而且强大的日志功能只用花费极低地计算和存储性能。而且它最大可支持的存储空间为 18EB,这几乎满足了所有需求。

就像拿到了一张未裁切的完整纸张那样,我们首先要进行裁切以方便使用,然后在裁切后的纸张上画格以便能书写工整。在拿到了一块新的硬盘存储设备之后,也需要先分区,然后再格式化文件系统,最后才能挂载并正常使用。硬盘的分区操作取决于需求和硬盘大小,可以选择不进行分区,但是必须对硬盘进行格式化处理。

5. 硬盘格式化

日常在硬盘需要保存的数据实在太多了,因此 LInux 系统中有一个名为 super block的“硬盘地图”。Linux 并不是把文件内容 直接写入到这个“硬盘地图”里面,而是在里面记录着整个文件系统的信息,因为如果把所有的文件内容都写入到 这里面,它的体积将会变得非常大,而且文件内容的查询与写入速度会变得很慢。Linux 只是把每个文件的权限与属性记录在 inode 中,而且每个文件占用一个独立的 inode 表格,该表格的大小默认为 128 字节,里面记录着如下信息:

该文件的访问权限(read,write,execute);
该文件的所有者与所属组(owner,group);
该文件的大小(size);
该文件的创建或内容修改时间(ctime);
该文件的最后一次访问时间(atime);
该文件的修改时间(mtine);
文件的特殊权限(SUID,SGID,SBIT);
该文件的真实数据地址(point);

而文件的实际内容则保存在 block 块中(大小可以是1kB、2KB或4KB),一个 inode 的默认大小仅为 128B(Ext3),记录一个block 则消耗 4B。当 文件的 inode 被写满后,Linux 系统会自动分配出一个 block 块,专门用于像 inode 那样记录其他 block 块的消息,这样把各个 block 块的内容串到一起,就能够让用户读到完整的文件内容了。对于存储文件内容的 block 块,有下面两种常见情况(以 4KB 的 block 大小为例进行说明)。

情况1:文件很小(1KB),但是依然会占用一个 block,因此会潜在的浪费 3KB。
情况2:文件很大(5KB),那么会占用两个block(5KB-4KB后剩下的 1KB也要占用一个 block)。

计算机系统在发展过程中产生了众多的文件系统,为了是用户在读取或写入文件时不用关心低层的硬盘结构,Linux内核中的软件层为用户提供了一个 VFS(Virtual File System,虚拟文件系统)接口,这样用户实际上在操作文件时就是统一对这个虚拟文件系统进行操作了。
image

上图为VFS的架构示意图。从中可见,实际文件系统在 VFS 下隐藏了自己的特性和细节,这样用户在日常使用时会觉得“文件系统都是一样的”,也就可以随意使用各种命令在任何文件系统中进行各种操作了(比如使用cp命令来复制文件)。

推荐阅读