Linux基础IO(七)之理解文件系统
文章目录
- 文件系统的理解
- 问题
- 如何理解“目录”?
文件系统的理解
我们使用ls -l
的时候看到的除了看到文件名,还看到了文件元数据。
每行包含7列:
模式
硬链接数
文件拥有者
文件所属组
大小
最后修改时间
文件名
ls -l读取存储在磁盘上的文件信息,然后显示出来
inode是以分区为单位的,如:第一个分区从0~n
,第二分区从0~m
一个分区要使用的 inode
数量在格式化的时候确定好的。
格式化:写入文件系统的信息。
可能会出现的现象 inode
用完了,数据块还有/ inode
还有,数据块用完了。
块>扇区:预加载。
上面的执行结果有几个信息需要解释清楚inode
为了能解释清楚inode
我们先简单了解一下文件系统
有了磁盘要做的事情:
1.分区 2.格式化(写入文件系统信息)
Linux ext2文件系统,上图为磁盘文件系统图(内核内存映像肯定有所不同),
磁盘是典型的块设备,硬盘分区被划分为一个个的block。
一个block的大小是由格式化的时候确定的,并且不可以更改。
例如mke2fs的-b选项可以设定block大小为1024、2048或4096字节。
而上图中启动块(Boot Block)的大小是确定的,
Block Group:ext2文件系统会根据分区的大小划分为数个Block Group。
而每个Block Group都有着相同的结构组成。
超级块(Super Block):存放文件系统本身的结构信息。
记录的信息主要有:block和 inode的总量,未使用的block和inode的数量,
一个block和inode的大小,最近一次挂载的时间,最近一次写入数据的时间,最近一次检验磁盘的时间等其他文件系统的相关信息。
Super Block的信息被破坏,可以说整个文件系统结构就被破坏了
GDT,Group Descriptor Table:块组描述符,描述块组属性信息.
块位图(Block Bitmap):Block Bitmap中记录着Data Block中哪个数据块已经被占用,哪个数据块没有被占用
inode位图(inode Bitmap):每个bit表示一个inode是否空闲可用。
i节点表 : 存放文件属性 如 文件大小,所有者,最近修改时间等
数据区:存放文件内容
查看 inode
编号:
ls -li
stat
命令能够看到更多信息
问题
1.新建一个文件,系统要做什么?
在系统的某条路径里新建,
这条路径能确定在哪个分区的哪个分组里
在分区层面上分配inode
,可以根据inode
的范围来确定分组。
将inode bitmap
对应的编号由0置1,
然后根据inode
编号在inode table
里找到对应的inode
,
将文件属性往里填,填完就算新建成功了。
如果要写入,先确定写入的大小,
遍历block bitmap
,找到没有使用的块号,
把对应的块号填到属性的数组里,然后跳转,把数据写到块里。
(如何获得inode
?查GDT的inode
的使用情况,
然后查找inode bitmap
最近的没有被使用的编号,
inode
=inode bitmap
+偏移量)
2.删除一个文件,系统要做什么?
找到文件对应的inode
,然后根据文件路径找到分区找到分组,
inode
编号 - 组的起始的inode
编号,
就能找到block bitmap
对应的比特位,
根据inode
里的属性数组的块号,
修改block bitmap
对应的比特位,由1置0
最后把inode bitmap
里的值也置0
删除其实就是修改了两个bitmap
位图的数值。
删除=允许被覆盖。
如果真的删除–把数据清空,
会导致IO过多,系统效率降低,
会减少对应设备的寿命。
所以直接覆盖,就可以解决降低效率问题。
3.查找一个文件,系统要做什么?
找到文件inode
,找到inode bitmap
为1说明有效,
就可以去读inode table
,把属性拿出来。
如果要文件内容,就通过文件属性里的数组,
通过数组找到所有的数据块,将内容拼接好。
根据路径找到对应的分区,根据inode
找到分组,
根据inode
找到文件属性的数组,根据数组找到数据块。
把数据块加载到内存里,然后读出文件内容。
4.修改一个文件,系统要做什么?
找到inode
,就能找到inode
的文件属性,然后就可以直接更新数据,
或者通过inode
找到文件属性中的数组,通过数组找到文件内容进行修改,
不够空间就重新申请数据块,把块号往数组映射里填,在把数据写到数据块里。
所有的问题 --> 我怎么知道一个文件inode
编号?
使用者从来没关心过 inode
,用的是文件名。
如何理解“目录”?
目录是文件,也有自己的inode
,目录也有自己的属性。文件=内容+属性
目录有内容吗?要不要数据块?
目录也有数据块。
目录里面的数据块放什么呢?
该目录下,文件的文件名 和 对应文件的inode
的映射关系!!(文件名:inode
)key-value
1.为什么同一个目录下不能有同名的文件?
因为要通过文件名(key值)找到inode
,重名冲突了文件系统就无法找到指定的文件了。
2.目录下,没有w,我们无法创建文件
新建删除文件需要有w权限,
没有w权限就算创建了目录,
但是无法将文件名和inode
的映射关系写到目录文件的数据块里。
3.目录下,没有r,我们无法查看文件
当我们要读文件对应的文件名或者其他属性时,
要先读取这个文件的inode
,
目录不让读,那么文件名和inode
的映射关系读不到,拿不到inode
找不到inode
就不能能查看该文件的信息。
4.目录下,没有x,我们就无法进入这个目录
cd进入目录,就是要将目录名拼到环境变量里,
x不让更新环境变量,就进入不了目录了。
–> 目录是文件,也有inode
编号,
我只知道目录的文件名,我怎么知道我目录的inode
呢?
目录也是上级目录的子目录,所以要找上级目录的inode
,读上级目录的数据块,
拿到现目录的文件名与inode
的映射关系。
递归查找,找到根目录(根目录文件名固定,有对应的inode
),
读取根目录的数据块,就可以找到子目录的inode
,继续递归就可以找到了。
所以找一个文件时,要给文件带路径。现目录->…->根目录 根目录->…->现目录
系统找文件必须带路径。相对目录前提是当前的目录已经被找到了。
Linux系统会把用户最常访问的路径(目录inode
及各种属性信息)信息缓存起来。
dentry
缓存,要的时候直接从中拿数据,就不用读盘了。
将属性和数据分开存放的想法看起来很简单,但实际上是如何工作的呢?
我们通过touch
一个新文件来看看如何工作。
创建一个新文件主要有一下4个操作:
- 存储属性
内核先找到一个空闲的i节点(这里是263466)。内核把文件信息记录到其中。
- 存储数据
该文件需要存储在三个磁盘块,内核找到了三个空闲块:300,500,800。
将内核缓冲区的第一块数据复制到300,下一块复制到500,以此类推。
- 记录分配情况
文件内容按顺序300,500,800存放。内核在inode
上的磁盘分布区记录了上述块列表。
- 添加文件名到目录
新的文件名abc。
linux
如何在当前的目录中记录这个文件?
内核将入口(263466,abc
)添加到目录文件。
文件名和inode
之间的对应关系将文件名和文件的内容及属性连接起来。