常见的硬盘如上图所示,每个盘片分多个磁道,每个磁道分多个扇区,每个扇区512字节,是硬盘的最小存储单元,但是在操作系统层面会将多个扇区组成块(block),是操作系统存储数据的最小单元,通常是8个扇区组成4k字节的块。
对于linux文件系统,需要考虑以下几点: 文件系统需要有严格的组织形式,使文件能够以块为单位存储 文件系统需要有索引区,方便查找一个文件分成的多个块存在了什么位置 如果有文件近期经常被读写,需要有缓存层 文件应该用文件夹的形式组织起来方便管理和查询 linux内核要在自己的内存里维护一套数据结构,保持哪些文件被哪些进程打开和使用linux里面一切皆文件,都有以下几种文件(从ls -l结果的第一位标识位可以看出来):
– 表示普通文件 d 表示文件夹 c 表示字符设备文件 b 表示块设备文件 s 表示套接字socket文件 l 表示软链接inode和块存储
下面就以ext系列格式为例来看一下文件是如果存在硬盘上的。首先文件会被分成一个个的块,分散得存在硬盘上,就需要一个索引结构来帮助我们找到这些块以及记录文件的一些元信息,这就是inode,其中i代表index。inode数据结构如下:
其中__le32 i_block[ext4_n_blocks]存储了到数据块的引用,ext4_n_blocks定义如下:
在ext2和ext3中i_block前12项存储了直接到数据块的引用,第13项存储的是到间接块的引用,在间接块里存储着数据块的位置,以此类推,第14项里存储着二次间接快的位置,第15项里存储着三次间接块的位置,如下图所示:
不难看出,对于大文件,需要多次读取硬盘才能找到相应的块,在ext4中就提出了extents tree来解决这一问题,其核心思想就是把连续的块用开始位置加块的个数来表示,不再是一个一个去记录每一个块的位置,这样就能节约存储空间。首先,它将i_block中原来415=60字节的空间换成了一个extent header(ext4_extent_header)加4个extent entry(ext4_extent),因为ext4_extent_header和ext4_extent都是占用了12字节。ee_len中的第一个bit用来判断是否初始化,所以它还能存储最大32k个数,所以一个extent entry里最大可以存32k4k=128m的数据,如果一个文件大于4128m=512m或者这个文件被分散到多于4个不连续的块中存储,我们就需要扩展inode中的i_block结构。它的extent entry就要从ext4_extent被换成ext4_extent_idx结构体,它所指向的是一个块,有4k字节,除去header占用的12字节,还能存340个ext4_extent,最大可以存340128m=42.5g的数据。可以看出这种索引结构在文件用连续的块存储时非常高效。
举一个/var/log/messages文件的例子如下图所示:
inode位图和块位图
硬盘上会有专门存放块数据的区域也会有存放inode的区域,但是当我们要新建一个文件时,就需要知道哪个inode区域和哪个块是空的,这就需要分别用一个块来存储inode位图和一个块来存储块位图,每一个bit为1表示占用,为0表示未占用。但是一个块最多有4k*8=32k个位,也就最多能表示32k个块的状态,所以需要让这些块组成一个块组,来搭出更大的系统。
硬链接和软链接
硬链接与原文件共用一个inode,且inode不能跨文件系统,所以硬链接也不能跨文件系统。
软链接有自己inode,只是打开文件时是指向另外一个文件,所以可以跨文件系统且当原文件被删除后仍存在。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对服务器之家的支持。
原文链接:https://segmentfault.com/a/1190000019361677