【README】
1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐;
2.文件:煮熟的磁盘,或熟磁盘;
- 本节的主要内容是讨论 如何从文件得到盘块号;
3.磁盘操作抽象(复习)
- 第1层抽象:通过盘块号读写磁盘(或逻辑盘块号);参见 第24讲 内容;
- 第2层抽象:用队列缓存多个进程读写的盘块号;参见 第24讲 内容;
- 第3层抽象:文件(或通过文件操作磁盘); 参见 第25讲 内容;
4.字符流到盘块的映射
- 顺序结构的文件存储方式;
- 链式结构的文件存储方式;
- 索引结构的文件存储方式;
【1】对磁盘使用的第3层抽象-文件
1)为什么引入文件 ?
【图解】
1)用户眼里的文件: 字符序列 或 字符流;
2)磁盘上的文件:文件内容分散存储在多个相邻盘块(逻辑),或多个相邻扇区(物理);
3)文件:
- 建立字符流到盘块集合的映射关系,或字符流到扇区集合的映射关系;
- 使用映射关系就可以把文件计算出盘块号;
【2】字符流到盘块号的映射
1)操作系统负责维护这个映射关系(字符流到盘块号的映射关系);
【图解】
1)映射例子: test.c文件中的 200~212 字符对应盘块为 789;如 上层用户程序命令是把 200~212 的字符删除掉;
- 操作系统会解释这个文件字符删除命令,查找200~212对应的盘块号;
- 拿到盘块去创建一个磁盘读写请求,并放入请求队列;
- 磁盘控制器在完成上一个盘块的读写后,发出中断;
- 中断处理程序会发出命令让磁盘控制器使用电梯算法选择下一个盘块进行读写;
【2.1】连续(顺序)结构的文件存储方式
1)连续结构:
- 文件内容顺序存放在相邻盘块 ;
2)根据字符流如何计算出盘块号(非常重要*)
- 如 test.c 第0~99字符流放在盘块6;第100~199放在盘块7;第200~299放在盘块8;那所以200~212映射到盘块8。
- 计算逻辑也可以是 200/100 = 2;盘块偏移量是2,初始盘块号为6,所以目标盘块号是 6+2=8;
3)文件控制块结构体 FCB-file controll block
FCB就是inode;
文件名 | 起始块 | 块数 |
test.c | 6 | 3 |
4)连续结构的文件存储方式的问题
- 当test.c的内容不断增加,其所用盘块也会连续增加,增加到第14块(上图黄色标识)的时候,
- 而第14块原本是被 test2.c 占用的,为了 保证test.c文件的连续性,需要把test2.c 文件内容挪到其他地方,这就影响了文件读写的性能;
总结:连续结构的文件存储方式,适合读写,但不适合文件内容动态增长;
【2.2】链式结构的文件存储方式
【图解】
1)FCB 结构中的起始块是1;
2) 链表结构:
- test.c文件分散存储在 盘块10,盘块17,盘块9;3个盘块分别存储了 0~99,100~199,200~299 范围的字符;
3) 链表结构扫描方式:
- 所以要把 200~212范围的字符删除掉,由于是链表结构,磁盘控制器需要把盘块10,盘块17,盘块9依次读入内存,最终在盘块9中做操作;因为 盘块10的next指针指向盘块17,盘块17的next指针指向盘块9,盘块9的next指针为null, 所以需要依次读入链表上的盘块(链表的缺点);
总计:链式结构的文件存储方式
- 优点:适合动态增长;
- 缺点:读写性能慢,因为要从头开始扫描盘块号;
【2.3】索引结构的文件存储方式
1)关于inode:文件信息数据结构inode 中的 i 就是指的是 index索引,而node指的是 文件控制块FCB;
2)索引: 索引就是目录;
【图解】基于索引结构的文件存储方式访问磁盘步骤
- 1)步骤1:读入文件 test.c 的 inode 即 FCB;
- 2)步骤2:从FCB找到索引块19,说明盘块19 存储了文件内容的盘块索引(存储了字符流与盘块映射关系),则读入盘块19中的所有内容(如下表);
- 3)步骤3:计算盘块号。
索引块19存储的索引如下:
逻辑序号 | 盘块号 | 存储字符范围 |
0 | 9 | 0~99 |
1 | 17 | 100~199 |
2 | 1 | 200~299 |
3 | 10 | 300~399 |
4 | -1(null) |
所以要操作 200~212范围的字符,只需要用 200/100 = 2,获取下标2的盘块,即盘块1;
【总结】索引结构总结(重要 *)
- 适合顺序读写,因为索引是一个数组,带有连续下标;
- 也适合动态增长,因为多个索引项是分散的,不是连续的(但逻辑下标是连续的);
- (特别重要*)所有的linux, unix的文件系统使用的都是索引结构对字符流到盘块的映射;
-
【3】多级索引
【图解】
1)小文件inode的索引块直接指向数据块
- 即inode结构体中的索引块就是数据块,如 ptr1, ptr2, ptr3 等(如黄色部分);
2)中等文件inode 使用一阶间接索引
- 即 inode结构体中的索引块就是索引块,存储了文件内容使用的多个分散盘块号(分散盘块号的逻辑序号是连续的),如下表,盘块号9,17,1,10是分散的,但逻辑序号(下标)是连续的:
逻辑序号 | 盘块号 | 存储字符范围 |
0 | 9 | 0~99 |
1 | 17 | 100~199 |
2 | 1 | 200~299 |
3 | 10 | 300~399 |
4 | -1(null) |
然后再根据要操作的字符范围算出逻辑序号,进而找到盘块号,把盘块号封装到文件请求送入请求队列即可。
3)大型文件inode使用二阶或三阶间接索引
- 原理与一阶间接索引类似;
总结:多级索引(非常重要*)
- 使用三阶间接索引可以表示非常大的文件;
- 很小的文件(小文件)直接指向数据块,因此高效访问;
- 中等文件采用一阶间接索引,也不慢;
【小结】
- 1)如何从生磁盘抽象为文件?
- 核心是从字符流位置算出盘块号;
2)如何算出盘块号?
- 用到顺序结构,或链式结构,或索引结构提供的映射表。