Ext系列文件系统
目录
一:理解硬件
1.1磁盘、服务器、机柜、机房
1.2磁盘的物理结构
1.3磁盘的存储结构
1.4磁盘的逻辑过程
1.4.1理解
1.4.2真实过程
1.5 CHS&&LBA地址
二:文件系统
2.1 “块” 的概念
2.2 分区
2.3 inode概念
三:Ext2文件系统
3.1宏观认识
3.2Block Group
3.3块组内部构成
3.3.1超级块(Super Block)
3.3.2 GDT(Group Descriptor Table)
3.3.3 块位图(Block Bitmap)
3.3.4 inode位图(Inode Bitmap)
3.3.5 i节点表(Inode Table)
3.3.6Data Block
3.3.7总结
3.4inode和datablock映射
3.5文件名与目录
3.6路径解析
3.7路径缓存
3.8挂载分区
3.9文件系统总结
四:软硬链接
4.1硬链接
4.2软链接
编辑 4.3软硬链接对比
一:理解硬件
1.1磁盘、服务器、机柜、机房
机械磁盘是计算机中唯一的一个机械设备
磁盘---外设
特点:1.慢 2.容量大,价格便宜
1.2磁盘的物理结构
1.3磁盘的存储结构
扇区:是磁盘存储数据的基本单位,512字节,块设备
磁盘在摆动的本质:定位磁道(柱面)
磁盘盘片旋转的本质:定位扇面
每一个面都有一个磁头,读哪一个磁头本质就是写哪一面
如何定位一个扇区呢?
1.可以先定位磁头(header)
2.确定磁头要访问哪一个柱面(磁道)(cylinder)
3.定位一个扇区(sector)
4.CHS地址定位
文件=内容+属性 都是数据,无非就是占据那几个扇区的问题!能定位⼀个扇区了,能不能定位多个扇区呢?
扇区是从磁盘读出和写入信息的最小单位,通常大小为 512 字节。
磁头(head)数:每个盘片⼀般有上下两面,分别对应1个磁头,共2个磁头
磁道(track)数:磁道是从盘片外圈往内圈编号0磁道,1磁道...,靠近主轴的同心圆用于停靠磁 头,不存储数据
柱面(cylinder)数:磁道构成柱面,数量上等同于磁道个数
扇区(sector)数:每个磁道都被切分成很多扇形区域,每道的扇区数量相同
圆盘(platter)数:就是盘片的数量
磁盘容量=磁头数×磁道(柱面)数×每道扇区数×每扇区字节数
细节:传动臂上的磁头是共进退的
柱⾯(cylinder),磁头(head),扇区(sector),显然可以定位数据了,这就是数据定位(寻址)方式之一,CHS寻址方式。
CHS寻址
对早期的磁盘非常有效,知道用哪个磁头,读取哪个柱面上的第几扇区就可以读到数据了。 但是CHS模式支持的硬盘容量有限,因为系统用8bit来存储磁头地址,用10bit来存储柱面地 址,用6bit来存储扇区地址,而⼀个扇区共有512Byte,这样用CHS寻址⼀块硬盘最大容量为256*1024*63*512B=8064MB(1MB=1048576B)(若按1MB=1000000B来算就是 8.4GB)
1.4磁盘的逻辑过程
1.4.1理解
常见的磁盘:
磁带上面可以存储数据,我们可以把磁带“拉直”,形成线性结构
那么磁盘本质上虽然是硬质的,但是逻辑上我们可以把磁盘想象成为卷在⼀起的磁带,那么磁盘的逻 辑存储结构我们也可以类似于:
这样每⼀个扇区,就有了一个线性地址(其实就是数组下标),这种地址叫做LBA
1.4.2真实过程
柱面是⼀个逻辑上的概念,其实就是每⼀面上,相同半径的磁道逻辑上构成柱面。 所以,磁盘物理上分了很多面,但是在我们看来,逻辑上,磁盘整体是由“柱面”卷起来的。
所以,磁盘的真实情况是:
磁道: 某⼀盘面的某一个磁道展开:
即:一维数组
柱面: 整个磁盘所有盘面的同⼀个磁道,即柱面展开:
柱面上的每个磁道,扇区个数是一样的,即:二维数组
整盘:
整个磁盘不就是多张二维的扇区数组表(三维数组?)
所有,寻址⼀个扇区:先找到哪⼀个柱面(Cylinder),在确定柱面内哪⼀个磁道(其实就是磁头位置, Head),在确定扇区(Sector),所以就有了 CHS 。
我们之前学过C/C++的数组,在我们看来,其实全部都是⼀维数组:
所以,每⼀个扇区都有一个下标,我们叫做 LBA(Logical Block Address) 地址,其实就是线性地址。所以怎么计算得到这个LBA地址呢?
OS只需要使用LBA就可以了!!LBA地址转成CHS地址,CHS如何转换成为LBA地址。谁做啊??磁盘 自己来做!固件(硬件电路,伺服系统)
1.5 CHS&&LBA地址
CHS转成LBA:
磁头数*每磁道扇区数 = 单个柱面的扇区总数
LBA = 柱面号C*单个柱⾯的扇区总数 + 磁头号H*每磁道扇区数 + 扇区号S-1
即:LBA= 柱面号C*(磁头数*每磁道扇区数) +磁头号H*每磁道扇区数+扇区号S-1
扇区号通常是从1开始的,而在LBA中,地址是从0开始的,柱面和磁道都是从0开始编号的
总柱面,磁道个数,扇区总数等信息,在磁盘内部会自动维护,上层开机的时候,会获取到这些参 数。
LBA转成CHS:
柱面号C = LBA // (磁头数*每磁道扇区数)【就是单个柱面的扇区总数】( "//": 表示除取整)
磁头号H = (LBA % (磁头数*每磁道扇区数)) // 每磁道扇区数
扇区号S = (LBA % 每磁道扇区数) + 1
所以:从此往后,在磁盘使用者看来,根本就不关心CHS地址,而是直接使用LBA地址,磁盘内部自己转换。所以: 从现在开始,磁盘就是⼀个元素为扇区的⼀维数组,数组的下标就是每⼀个扇区的LBA地址。OS使用磁盘,就可以用⼀个数字访问磁盘扇区了。
二:文件系统
2.1 “块” 的概念
其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样 效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。硬盘的每个分区是被划分为一个个的”块”。一个”块”的大小是由格式化的时候确定的,并且不可以更改,最常见的是4KB,即连续八个扇区组成⼀个”块”。”块”是文件存取的最小单位。
注意: 磁盘就是⼀个三维数组,我们把它看待成为一个"一维数组",数组下标就是LBA,每个元素都是扇 区
每个扇区都有LBA,那么8个扇区一个块,每⼀个块的地址我们也能算出来。
知道LBA:块号 = LBA/8 , 知道块号:LAB=块号*8 + n(n是块内第几个扇区)
2.2 分区
其实磁盘是可以被分成多个分区(partition)的,以Windows观点来看,你可能会有一块磁盘并且将它分区成C,D,E盘。那个C,D,E就是分区。分区从实质上说就是对硬盘的⼀种格式化。但是Linux的设备都是以文件形式存在,那是怎么分区的呢?
柱面是分区的最小单位,我们可以利用参考柱面号码的方式来进行分区,其本质就是设置每个区的起始柱面和结束柱面号码。此时我们可以将硬盘上的柱面(分区)进行平铺,将其想象成⼀个大的平面,如下图所示:
2.3 inode概念
之前我们说过文件=数据+属性 ,我们使用 ls -l 的时候看到的除了看到文件名,还能看到文件元数据(属性)
每行包含7列 :模式 ,硬链接数 ,文件所有者 ,组,大小 ,最后修改时间 ,文件名
ls -l读取存储在磁盘上的文件信息,然后显示出来
其实这个信息除了通过这种方式来读取,还有⼀个stat命令能够看到更多信息
到这我们要思考⼀个问题,文件数据都储存在”块”中,那么很显然,我们还必须找到⼀个地方储存 文件的元信息(属性信息),比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为”索引节点”
每一个文件都有对应的inode,里面包含了与该文件有关的⼀些信息。为了能解释清楚inode,我们需要是了解⼀下文件系统。
Linux下文件的存储是属性和内容分离存储的
Linux下,保存文件属性的集合叫做inode,一个文件,⼀个inode,inode内有一个唯一的标识符,叫做inode号
文件名属性并未纳入到inode数据结构内部
inode的大小⼀般是128字节或者256
任何文件的内容大小可以不同,但是属性大小⼀定是相同的
1. 我们已经知道硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,读取的基本单位 是”块”。“块”又是硬盘的每个分区下的结构,难道“块”是随意的在分区上排布的吗?那要怎 么找到“块”呢? 2. 还有就是上面提到的存储文件属性的inode,又是如何放置的呢?
文件系统就是为了组织管理这些的!!
三:Ext2文件系统
3.1宏观认识
我们想要在硬盘上储文件,必须先把硬盘格式化为某种格式的文件系统,才能存储文件。文件系统的目的就是组织和管理硬盘中的文件。在Linux系统中,最常见的是ext2系列的文件系统。ext2文件系统将整个分区划分成若干个同样大小的块组(Block Group),如下图所示。只要能管理⼀个 分区就能管理所有分区,也就能管理所有磁盘文件。
上图中启动块(Boot Block/Sector)的大小是确定的,为1KB,由PC标准规定,用来存储磁盘分区信息和启动信息,任何文件系统都不能修改启动块。启动块之后才是ext2文件系统的开始。
3.2Block Group
ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相同的结构组 成
3.3块组内部构成
3.3.1超级块(Super Block)
存放文件系统本身的结构信息,描述整个分区的文件系统信息。记录的信息主要有:bolc和inode的总量,未使用的block和inode的数量,一个block和inode的大小,最近一次挂载的时间,最近⼀次写入数据的时间,最近⼀次检验磁盘的时间等其他文件系统的相关信息。Super Block的信息被破坏,可 以说整个文件系统结构就被破坏了
超级块在每个块组的开头都有一份拷贝(第⼀个块组必须有,后面的块组可以没有)。为了保证文件系统在磁盘部分扇区出现物理问题的情况下还能正常工作,就必须保证文件系统的super block信 息在这种情况下也能正常访问。所以一个文件系统的super block会在多个block group中进行备份, 这些super block区域的数据保持⼀致。
3.3.2 GDT(Group Descriptor Table)
块组描述符表,描述块组属性信息,整个分区分成多个块组就对应有多少个块组描述符。每个块组描述符存储⼀个块组的描述信息,如在这个块组中从哪里开始是inode Table,从哪里开始是Data Blocks,空闲的inode和数据块还有多少个等等。块组描述符在每个块组的开头都有⼀份拷贝。
3.3.3 块位图(Block Bitmap)
Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
3.3.4 inode位图(Inode Bitmap)
每个bit表示⼀个inode是否空闲可用。
3.3.5 i节点表(Inode Table)
存放文件属性如文件大小,所有者,最近修改时间等
当前分组所有Inode属性的集合
inode编号以分区为单位,整体划分,不可跨分区
3.3.6Data Block
数据区:存放文件内容,也就是⼀个⼀个的Block。根据不同的文件类型有以下几种情况:
对于普通文件,文件的数据存储在数据块中。
对于目录,该目录下的所有文件名和目录名存储在所在目录的数据块中,除了文件名外,ls -l命令 看到的其它信息保存在该文件的inode中。
Block 号按照分区划分,不可跨分区
3.3.7总结
一个分区使用相同的文件系统,不同分区可以使用不同文件系统。
存在inode table使用完,但是datablocks没有使用完的情况,反之不存在。
3.4inode和datablock映射
inode内部存在 __le32 i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ ,
EXT2_N_BLOCKS =15,就是用来进行inode和block映射
这样文件=内容+属性,就都能找到了。
知道inode号的情况下,在指定分区,请解释:对文件进行增、删、查、改是在做什么?
1.增:通过inode找到当前对应的数据块,增加内容,如果数据块大小不够,系统就会重新分配行的数据块,更新inode数据
2.删:根据inode找到对应的要删除的数据块,让对应的inode和block的数据无效(解除映射关系……)
3.查:根据inode查找相关属性
4.改:先根据inode找到对应数据块,进行增删操作
下面,通过touch⼀个新文件来看看如何工作。
创建一个新文件主要有一下4个操作:
1. 存储属性 :内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。
2. 存储数据 :该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。将内核缓冲区的第一块数据复制到300,下一块复制到500,以此类推。
3. 记录分配情况 文件内容按顺序300,500,800存放。内核在inode上的磁盘分布区记录了上述块列表。
4. 添加文件名到目录 新的文件名abc。linux如何在当前的目录中记录这个文件?
内核将入口(263466,abc)添加到目录文 件。文件名和inode之间的对应关系将文件名和文件的内容及属性连接起来。
3.5文件名与目录
但是我们访问文件,都是用的文件名,没用过inode号啊?
目录是文件吗?如何理解?
Linux下一切皆文件!目录也是文件,但是磁盘上没有目录的概念,只有文件属性+文件内容的概念。目录的属性不用多说,内容保存的是:文件名和Inode号的映射关系
代码验证:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>int main(int argc, char *argv[])
{if (argc != 2){fprintf(stderr, "Usage: %s <directory>\n", argv[0]);exit(EXIT_FAILURE);}DIR *dir = opendir(argv[1]); // 系统调⽤,⾃⾏查阅if (!dir){perror("opendir");exit(EXIT_FAILURE);}struct dirent *entry;while ((entry = readdir(dir)) != NULL){ // 系统调⽤,⾃⾏查阅// Skip the "." and ".." directory entriesif (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0){continue;}printf("Filename: %s, Inode: %lu\n", entry->d_name, (unsigned long)entry->d_ino);}closedir(dir);return 0;
}
所以,访问文件,必须打开当前目录,根据文件名,获得对应的inode号,然后进行文件访问
所以,访问文件必须要知道当前工作目录,本质是必须能打开当前工作目录文件,查看目录文件的 内容!
3.6路径解析
打开当前工作目录文件,查看当前工作目录文件的内容?当前工作目录不也是文件吗?我们访问 当前工作目录不也是只知道当前工作目录的文件名吗?要访问它,不也得知道当前工作目录的inode 吗?
答案1:所以也要打开:当前工作目录的上级目录,额....,上级目录不也是目录吗??不还是上面的问题吗?
答案2:所以类似"递归",需要把路径中所有的目录全部解析,出口是"/"根目录。
最终答案3:而实际上,任何文件,都有路径,访问目标文件,比如:
/home/whb/zjiu/250802/test.c 都要从根目录开始,依次打开每⼀个目录,根据目录名,依次访问每个目录下指定的目录,直到访问到test.c。这个过程叫做Linux路径解析。
所以,我们知道了:访问文件必须要有目录+文件名=路径的原因
根目录固定文件名,inode号,无需查找,系统开机之后就必须知道
可是路径谁提供?
访问文件,都是指令/工具访问,本质是进程访问,进程有CWD!进程提供路径。
open文件,提供了路径,可是最开始的路径从哪立来?
所以Linux为什么要有根目录,根目录下为什么要有那么多缺省目录?你为什么要有家目录,你自己可以新建目录?
上面所有行为:本质就是在磁盘文件系统中,新建目录文件。而你新建的任何文件,都在你或者系 统指定的目录下新建,这不就是天然就有路径了嘛!
系统+用户共同构建Linux路径结构
文件描述符,进程关系:
3.7路径缓存
问题1:Linux磁盘中,存在真正的目录吗?
答案:不存在,只有文件。只保存文件属性+文件内容
问题2:访问任何文件,都要从/目录开始进行路径解析?
答案:原则上是,但是这样太慢,所以Linux会缓存历史路径结构
问题3:Linux目录的概念,怎么产生的?
答案:打开的文件是目录的话,由OS自己在内存中进行路径维护
Linux中,在内核中维护树状路径结构的内核结构体叫做: struct dentry
注意:
1.每个文件其实都要有对应的dentry结构,包括普通文件。这样所有被打开的文件,就可以在内存中 形成整个树形结构
2.整个树形节点也同时会属于LRU(Least Recently Used)结构中,进行节点淘汰
3.整个树形节点也同时会属于Hash,便于快速查找
4.更重要的是,这个树形结构,整体构成了Linux的路径缓存结构,打开访问任何文件,都在先在这棵树下根据路径进行查找,找到就返回属性inode和内容,没找到就从磁盘加载路径,添加dentry 结构,缓存新路径
3.8挂载分区
我们已经能够根据inode号在指定分区找文件了,也已经能根据目录文件内容,找指定的inode了,在指定的分区内,我们可以为所欲为了。可是:
问题:inode不是不能跨分区吗?Linux不是可以有多个分区吗?我怎么知道我在哪一个分区???
/dev/loop0 在Linux系统中代表第⼀个循环设备(loop device)。循环设备,也被称为回环设备或者loopback设备,是一种伪设备(pseudo-device),它允许将文件作为块设备 (block device)来使用。这种机制使得可以将文件(比如ISO镜像文件)挂载(mount)为文件系统,就像它们是物理硬盘分区或者外部存储设备⼀样
分区写入件系统,无法直接使用,需要和指定的目录关联,进行挂载才能使用。
所以,可以根据访问目标文件的"路径前缀"准确判断我在哪⼀个分区。
3.9文件系统总结
以下图片是从网上找的,旨在从不同角度说明文件系统
四:软硬链接
4.1硬链接
我们看到,真正找到磁盘上文件的并不是文件名,而是inode。其实在linux中可以让多个文件名对应于同一个inode。
abc和def的链接状态完全相同,他们被称为指向文件的硬链接。内核记录了这个连接数,inode 263466的硬连接数为2。
我们在删除文件时干了两件事情:1.在目录中将对应的记录删除,2.将硬连接数-1,如果为0,则 将对应的磁盘释放。
4.2软链接
硬链接是通过inode引用另外⼀个文件,软链接是通过名字引用另外⼀个文件,但实际上,新文件和被引用文件的inode不同,应用常见上可以想象成⼀个快捷方式。
4.3软硬链接对比
软连接是独立文件,有独立的inode,软链接内容上保存的是目标文件的路径,类似Windows的快捷方式
硬链接不是独立文件,没有独立的inode,本质是文件名和目标文件inode的映射关系
Linux不允许对目录新建硬链接,根目录除外