您现在的位置是:首页 >技术杂谈 >【Linux】磁盘与文件系统网站首页技术杂谈
【Linux】磁盘与文件系统
目录
一、磁盘的物理结构
磁盘的物理结构如图所示:
其中具体的物理存储结构如下:
磁盘中存储的基本单元为扇区,一个扇区的大小是512字节或者4kb,这里我们暂且认定为512字节。一般磁盘,所有的扇区都是512字节。同半径的所有扇区构成了一圈磁道。
我们要读取指定数据,就需要先根据磁头编号确定使用哪一个盘面,再确定读取哪一个磁道,最后根据扇区的编号定位扇区即可。其中通过磁头(head)、柱面(磁道)(cylinder)、扇区(sector) 来定位扇区的方法称为 CHS 定位法。
一个普通文件包括属性 + 内容,本质上都是数据,占据一个或多个扇区,我们既然能够用 CHS 定位任意一个扇区,就能定位任意多个扇区,从而将文件从硬件角度读取或者写入。
二、磁盘逻辑抽象
我们已经知道如果OS能够得知CHS地址,就能访问任意一个扇区。但是因为OS是软件,磁盘是硬件,为了防止硬件发生迭代变化而导致OS也要跟着变化,就要做好OS与硬件的解耦工作,因此OS内部使用的并不是CHS地址。
为了减少进行IO操作的频率,OS与外设进行IO操作的基本单位大小是4KB(可以调整)。就算只需要修改一个字节的数据,也需要把这个数据所在的4KB大小的数据都加载进内存,修改好后再统一写回磁盘,因此我们把磁盘称为块设备。OS需要有一套新的地址来进行块级别的访问。
把磁盘磁道看作一个连续的空间结构:
扇区就相当于连续的数组,此时定位一个扇区就只需要一个数组下标了。由于OS是以4KB为单位进行IO的,所以一个OS级别的文件块要包括8个扇区。OS不关心扇区的概念,计算机常规的访问地址是通过 起始地址 + 偏移量 的方式进行的,因此OS访问数据块时,只需要知道数据块的起始地址 + 4KB 就可以了,把数据块看作一种类型。
所以块的地址本质就是数组的一个下标N,以后就可以采用下标N的方式定位任意一个块了。这种寻址方式被称为 LBA ,即逻辑块地址。
获得 LBA 地址后,通过简单的数学计算就可以转换成磁盘的 CHS 地址。假如已知 LBA = 6500 ,磁盘一个磁面的大小为 5000 ,一个磁道的大小为 1000 。则其对应的地址是第 2 个磁面,第 6 个磁道,第 500 个扇区。
从此之后,对于磁盘的管理就被抽象成了对一个大数组的管理。
三、文件系统
由于磁盘很大,为了更加方便的管理,OS对磁盘块进行了分区。分区后再对每一个磁盘区域进行分组。具体结构如下:
在OS对磁盘进行分区时,会在最开始的位置设置一个 Boot Block ,这段区域里面主要保存与OS相关的内容,比如分区表、镜像地址等等。一般而言这个分区存在于 0 号盘面的 0 号磁道的 1 号扇区。当用户开机时,OS会加载磁盘的驱动,读取磁盘的分区表,再从特定分区的开始位置读取到OS所在的地址,并加载OS,此时OS才算真正运行起来。
在之后是OS对每一个分区进行分组形成的诸多 Block group 。 每一个 Block group 都有上图所示的 6 块区域。
1、Super Block
Super Block 保存的是文件系统的所有属性信息,包括文件系统的类型、整个分组的情况。记录的信息主要有: bolck 和 inode 的总量,未使用的 block 和 inode 的数量,一个 block 和 inode 的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。
后面每一个 Block group 中可能都有一个这样的超级块,并且每一个超级快存储的数据都完全相同,统一更新。这样做的目的是防止超级块区域坏掉,如果出现故障,整个分区不可再被使用,因此要做好备份。
2、Group Descriptor Table
GDT 为组描述符,保存该组内的详细统计等属性信息。比如本组内从哪里到哪里是哪部分内容,本组被使用了多少等等。
3、inode Table
一般而言,我们把一个文件内部所有属性的集合称为 inode 节点,一般大小为 128 字节。一个文件有一个inode。一个分组内会有大量的文件,也就有大量的inode节点,所以在组内需要专门有一个区域来保存这些inode节点,这个区域叫做 inode Table ,也叫 inode 表。
在分组内部,每一个inode都有自己的inode编号,inode编号本身也属于对应文件的属性。 Linux查找一个文件,就是根据inode编号来查找的。
一个inode对应一个文件,该文件的inode属性和该文件对应的数据块是有映射关系的。
4、Data Blocks
文件的内容是变化的,用数据块来进行保存。所以要保存一个有效文件的内容,就需要 n 个数据块。如果有多个文件就需要多个数据块。这些数据块所在的区域就是 Data Blocks 。一个数据块的默认大小是 4KB 。
Linux查找一个文件,首先找到该文件的inode。在inode结构体内部有一个 int blocks[NUM] 数组,数组内记录了存储该文件内容的数据块的地址。一个分组中,百分之95以上的内容都是 Data Blocks 。
当操作系统要加载一个文件时,只加载该文件的 inode 节点。而 inode 节点中包含该文件内容数据块的映射关系,想要访问哪部分内容,就根据映射关系把哪一部分内容加载到内存中。
5、inode Bitmap
inode Bitmap 是一个位图结构,每个bit表示一个 inode 是否空闲可用。
6、Block Bitmap
Block Bitmap 是一个位图结构,记录着 Data Block 中哪个数据块已经被占用,哪个数据块没
有被占用。
四、Linux下文件系统
使用 ls 指定加上 -i 命令选项,就可以观察到文件的 inode :
1、inode与文件名
Linux系统只认inode编号,且文件的inode属性中不包含文件名,文件名只是给用户看的。
任何一个文件都一定在目录内部,目录本身也是文件,也有自己的inode和对应的数据块,目录的数据块里面保存的是该目录下文件名和文件inode编号对应的映射关系。而且在目录内,文件名与inode编号互为key值。
inode number 在一个分区内唯一有效,不能跨分区使用。根据 inode number 可以确定该文件在当前分区的哪一个分组。
2、文件的增删查改
2.1、查看文件内容
当用户访问一个目标文件的内容时,一定是在特定目录下访问的,具体流程如下:
- 先要在当前目录下找到目标文件的 inode number 。
- 一个目录也是文件,也隶属于一个分区,在该分区中通过目标文件的 inode number 找到分组,在该组的 inode Table 区域找到目标文件的 inode 。
- 通过目标文件的 inode 与对应 Data blocks 的映射关系,找到该文件的数据块,加载到OS,最后显示在显示器上。
2.2、删除文件
当用户删除一个目标文件时,具体流程如下:
- 在当前目录下,根据文件名找到目标文件的 inode number 。
- 根据 inode number 找到目标文件的 inode ,结合与对应 Data blocks 的映射关系,把 block bitmap 对应的比特位设置为 0 。
- 根据 inode number 把 inode bitmap 对应的比特位设置为 0 。
所以我们想要删除文件,就只需要修改位图即可,并没有把数据块清空。
2.3、创建文件
当用户创建一个目标文件时,一定是在一个目录下创建的。具体流程如下:
- OS在目录所处的分组里扫描 inode bitmap ,找到空余的位置并设置为 1 ,获得 inode number 。
- 把该文件创建出来后的默认属性填充到对应的 inode 中。
- 在当前所处的目录文件的 Data blocks 里追加一条新的文件名与 inode number 的映射关系。
2.4、补充内容
上面的内容包括分区、分组、填写系统属性等等,这些工作都是OS做的。分区完成之后,为了让分区能够正常使用,需要对分区做格式化操作,即OS向分区写入文件系统的管理属性信息,并做区域划分工作。如果区域划分之前已经做好了,那么格式化操作把位图结构清空,把属性字段设置为初始状态就可以了。
文件系统给 inode 与 Data blocks 建立映射关系通过数组来完成,由于 Data blocks 很大,为了能够映射的过来,数组采用了直接索引、二级索引、三级索引的方式来完成映射,因为不是重点内容,仅作了解,不作讲解。
文件系统中,有可能出现 inode 没用完,Data blocks 用完了。或者 inode 用完了,但是 Data blocks 还有剩余的情况。比如只建立一个文件,然后不断地往这一个文件中塞入数据,消耗 Data blocks。或者不断地建立空文件,消耗 inode 。这种问题目前是没有办法解决避免的。
五、软硬链接
1、软链接
建立软链接指令:
ln -s [目标文件] [软链接文件名称]
具体操作如下:
使用 my-soft 链接了 myfile.txt 。 my-soft 是一个链接文件。
观察到 my-soft 与 myfile.txt 的 inode number 不同,这说明软链接是一个独立的链接文件。有自己的 inode number,必有自己的inode属性和内容。软链接的内容是自己所指向的文件的路径。可以让用户快速的找到目标文件。
软链接的具体用法是,如果一个目标文件的路径非常深,我们每次访问目标文件都要写一遍很长的路径,效率不高。此时就可以使用软链接在工作目录制作一个软链接文件,以方便访问目标文件。类似 Windows 系统中的快捷方式。
2、硬链接
建立硬链接指令:
ln [目标文件] [软链接文件名称]
具体操作如下:
使用 my-hard 链接了 myfile.txt 。 my-hard 是一个普通文件。
观察到 my-hard 与 myfile.txt 的 inode number 相同,这说明硬链接与原文件是同一个文件,硬链接只是建立了新的文件名与老的inode number的映射关系,只修改了当前目录的内容。
my-hard 与 myfile.txt 的硬链接数都变成了 2 。意思是此时有两种方法可以找到该文件,分别对应两个文件名。硬链接数,本质是一种引用计数。
现在我们使用指令 unlink 来删除硬链接:
此时文件的硬链接数又变成了 1 。
接下来我们再创建一个目录文件,观察硬链接数:
可以看到目录文件的默认硬连接数是 2 。这是因为目录文件天生拥有两个硬链接,一个是它本身的名字,另一个是在该目录内部的 " . " 符号。如果目录文件的内部还有目录文件,那么该目录文件的硬链接数就变成了 3 :本身的名字、该目录内部的 " . " 符号、该目录内部的目录内的 " .. " 符号:
现在查看一下根目录的硬链接数:
硬链接数为 19 。根目录下的内容如下:
一般来说,一个目录文件的硬链接数 -2 就是该目录下的目录个数。
需要注意的是,用户无法自主给一个目录文件建立硬链接!
显示不能给目录建立硬链接。这是因为如果可以给目录建立硬链接,容易造成环路路径问题。OS没有把这个权限放给用户。
关于文件系统的相关内容就讲到这里,希望同学们多多支持,如果有不对的地方欢迎大佬指正,谢谢!