27.目录与文件系统
Posted PacosonSWJTU
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了27.目录与文件系统相关的知识,希望对你有一定的参考价值。
【README】
1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐;
2.第4层抽象:抽象整个磁盘到文件系统
【1】文件系统,抽象整个磁盘(第4层抽象)
【图解】整个磁盘抽象
1)磁盘存储的是一堆文件;一堆文件形成树状结构;
- 具体实现是:把整个磁盘的所有盘块进行抽象,组织;
- 所谓抽象就是用数据结构进行组织;
- 如一个文件对应一个inode,一个inode组织文件所有盘块,形成字符序列;
整个磁盘的文件以上述方式进行组织和抽象,形成给用户一个抽象的树状结构;
2)整个磁盘抽象为文件系统
- 文件系统就是映射, 从字符位置到盘块的映射;
- 底层结构是对上层的实现, 上层是对底层的抽象;
【2】整个磁盘的一堆文件如何映射
【2.1】目录树
1)多个文件如何组织
- 方式1) 所有文件放在一层目录下,即所有文件放在一个文件夹下 ;
- 缺点:不方便查找文件;
- 方式2) 每个用户一个目录,所有文件放在各自的用户目录下;
- 缺点:但每个用户的文件数量也很多,还是不方便查找;
2)目录树的文件组织方式
【图解】引入目录树之后,把N个文件进行K次划分,则划分后的子集的文件数量为 O(logkN) ;
划分算法可以参考分治思想:
- 第1次划分: 把N个文件平均划分为2个子集;
- 第2次划分: 把每个子集再平均划分为2个子集,共得到4个子集;
- 第K次划分: 把 K-1次划分得到的每个子集,再划分为2个子集,共得到 2^K-1 个子集;
3)引入了目录
- 如 var, my , data 等叫做目录,目录下面有子目录集合和文件集合;
- 多个目录构成目录树;
4)目录是什么?
- 实现目录成为关键性问题 ;
【2.2】目录的实现
1)目录怎么用?
- 文件路径: /my/data/a ;多个路径就构成了目录树; 其中非叶子节点 my,data是目录;
【图解】访问磁盘上的目录
- 步骤1: 根据目录(文件)路径 /my/data/a 可以找到文件a的inode,或FCB;inode存储了字符到盘块号的映射关系;
- 步骤2: 根据inode可以找到文件a对应的盘块号,(如果没有字符起始位置,则起始位置是0);
- 步骤3:把盘块号送入请求队列,再由驱动程序取出盘块号计算出CHS,发送out指令把CHS送入磁盘控制器;
2)如何根据路径或文件名(目录名)找到文件 inode
- 或目录存储了什么信息可以根据路径找到具体的文件;
【例】根据/my/data/ a 如何找到 a文件的inode ;
my目录下面有3个文件(或目录),data下面还有a文件;
方法1)目录存放该目录下的所有子目录(文件)的inode(FCB);
- 对于查找 /my/data/a 的inode 需要列出 my目录下的所有子目录,包括data,count,mail;然后所有子目录与data做比较并选择得到data目录的inode;再列出data目录下的所有子目录,然后以此类推。
- 方法1的问题: 查找速度比较慢;因为 读取了 count,mail的fcb但这2个目录的fcb是用不到的;造成了浪费。
方法2)目录存放该目录下的所有子目录(文件)的inode(FCB)的编号(指针);
如下图所示。
【图解】目录的实现 (重要*)
- 当前目录存放子目录(文件)的inode(FCB)的编号(指针)。
- 磁盘抽象结构如下:
FCB数组(指针) | 数据盘块集合 |
[FCB0, FCB1, FCB2, FCB3, FCB4, FCB5, FCB6, FCB7, FCB8, FCB9, FCB10, ...] | <var,13><my,82> |
其中 FCB0 存储了根目录的FCB(第一个FCB就是根目录的FCB);
FCB1存储了 var目录的FCB;
FCB2存储了 my目录的FCB, ......
【例】目录的数据结构(结构体)
对于查找路径 /my/data/a表示的a目录的盘块号步骤:
- 步骤1:把所有根目录”/” 下的子目录项列表查询出来;
- 步骤2:根据目录项列表查找my目录的编号13(或下标13);
- 步骤3:根据编号13查找FCB数组就可以找到并读入目录my的FCB13;
- 步骤4:根据目录my的FCB13的数据块中的子目录项列表, 找到目录data的FCB编号103;
- my目录结构如下:
FCB数组(指针) | 数据盘块集合(子目录项列表) |
[FCB0, FCB1, FCB2, FCB3, FCB4, FCB5, FCB6, FCB7, FCB8, FCB9, FCB10, ...] | <data,103> <cont,225> <mail, 77> |
- 根据编号103,到FCB数组找到并读入103号下标的FCB,即data目录的FCB103;
- 步骤5:根据目录data的FCB103的数据块中的子目录项列表, 找到目录a的FCB编号205;
- a 目录结构如下:
-
FCB数组(指针)
数据盘块集合(子目录项列表)
[FCB0, FCB1, FCB2, FCB3, FCB4, FCB5, FCB6, FCB7, FCB8, FCB9, FCB10, ...]
<a,205>
- 根据编号205,到FCB数组找到205号下标的FCB,即a目录(文件)的FCB205;即,FCB205就是路径 /my/data/a 的FCB;
补充:接下来磁盘读写步骤 :
- FCB存储了盘块号,把盘块号送入请求队列;
- 磁盘驱动通过电梯算法从请求队列获取盘块号,并计算出CHS送入磁盘控制器;
- 磁盘控制器根据CHS操作磁盘进行读写;
3)根目录”/”信息从哪里来?
- 即 根目录下的子目录列表的FCB数组从哪里获取 ;
【注意】上图非常重要,它显示的是 整个磁盘格式化后的组成部分(非常重要*)
【图解】根目录信息存储了什么数据。
1)整个磁盘格式化以后,就会形成目录树结构,包括
- 引导块;
- 超级块;
- i节点位图(inode位图);
- 盘块位图;
- i节点(inode数组);第1项就是根目录inode;
- 数据区;
2)整个磁盘格式化后各个部分的内容构成:
- 引导块:操作系统引导扇区 ;
- 超级块:记录了 i节点位图,盘块位图的盘块大小;超级块起始盘块号加上i节点位图盘块大小,再加上盘块位图盘块大小就可以得到i节点的起始盘块,而i节点的第1块存储的就是根目录信息,根目录存储了 FCB数组指针,子目录项列表;
- i节点位图(Inode位图):新建一个文件,即新建一个inode,把该文件对应的inode设置为1;相反,删除一个文件(或inode),则该inode设置为0;
- 盘块位图: 各个盘块使用情况(0-空闲,1-占用);
补充: superblock 超级块非常重要;
- mount原理:要想使用一个磁盘或u盘,需要先把u盘 挂载 mount到系统;mount的作用就是读取磁盘或u盘的超级块到内存,解析出 i节点位图,盘块位图;
- 根据 i节点位图和盘块位图可以 计算出i节点的起始盘块号;
- 读取i节点的第1个盘块的内容,即根目录FCB的信息;根目录FCB存储了子目录项列表;
【小结】
- 以上内容介绍了一个目录树(逻辑)如何实现在磁盘(物理)上的;
【3】整个磁盘的映射
【图解】 读取 test.c文件的202~212 范围的字节流
- 步骤1:打开 test.c 文件;
- 根据超级块找到 inode节点的起始盘块号;读取inode节点部分的第1个盘块,即根目录PCB;根据根目录PCB可以找到 test.c文件的PCB(inode);具体细节参见 (对于查找路径 /my/data/a 表示的 a 目录的盘块号步骤);
- 步骤2:通过inode获取文件描述符 fd,把fd传入 read() 函数,找到盘块789;
- 步骤3:把盘块号789 添加到请求队列;
- 步骤4:磁盘完成上一次读写后,发出中断;磁盘驱动的中断处理程序从请求队列中获取盘块号789,并计算出CHS(柱面号,磁头号,扇区号);
- 步骤5:把CHS作为 out命令的参数送入磁盘控制器;
- 步骤6:磁盘控制器根据CHS读入对应扇区的数据到内存缓冲区;
- 步骤7:读入完成后,发出中断,中断处理程序唤醒睡眠的用户线程;
- 步骤8:用户线程被唤醒后,把内存缓冲区的数据根据用户程序的指令送入cpu做进一步处理;
以上是关于27.目录与文件系统的主要内容,如果未能解决你的问题,请参考以下文章