为什么需要『文件系统』
- 能够存储大量信息
- 信息能够脱离进程存在
- 多个进程能够并发访问有关信息
磁盘:能够长期存储,广泛使用。不过固态硬盘已经逐渐流行(好像没几年前那么贵了),磁盘支持两种基本操作读块 k,写块 k
有三个问题
- 如何找到信息
- 如何防止一个用户读取另一个用户数据
- 如何知道哪些块是空闲的
文件:进程创建的信息逻辑单元,文件是对磁盘的建模,可以把文件看成地址空间。
进程可以读取文件,也可以新建文件。文件存储的信息是持久的,不受进程的创建与终止影响。文件只能在其所有者明确删除它情况下才会消失。
文件系统:文件受到操作系统管理,操作系统中处理文件的部分称为『文件系统』。
本章前两节介绍文件和目录的用户接口,后面讨论文件系统实现。
4.1 文件
4.1.1 文件命名
文件命名规则:在不同系统中不同,有些区分大小写。
本章后面讨论没有指明文件系统,默认『FAT 文件系统』
许多操作系统支持文件名用原点隔开两部分,后半部分称为『文件扩展名』,通常表示文件一些信息。
某些系统(如 UNIX 所有版本),文件扩展名只是约定,并不强迫采用它。但某些处理文件的程序可能关心。
4.1.2 文件结构
UNIX 和 Windows 都采用『无结构的字节序列』,文件内容含义只在用户程序中解释。
字节序列好处是,提供最大的灵活性。用户程序可以任意加入内容,任意命名,操作系统不会提供帮助也不会构成障碍。
第二种、第三种文件结构看了一眼没必要增加笔记长度。
4.1.3 文件类型
目录:管理文件系统结构的系统文件,将在以后章节讨论
字符特殊文件:与输入输出有关,用来串行 I/O 类设备。
块特殊文件:用于磁盘类设备
普通文件:包含有用户信息的文件,一般分为 ASCII 文件和二进制文件。
ASCII 文件每行结束符在不同类型系统中表达可能不同,优势可以显示和打印,还可以用任何文本编辑器编辑。
二进制文件:打印出来无法理解,有一定内部结构,使用该文件的程序才了解这种结构。
魔数:在文件头,表明该文件是一个可执行文件
4.1.4 文件访问
顺序访问:从头按顺序读取文件的全部字节
随机访问文件:以任何次序读取文件中的字节或记录
两种方法可以指示从何处开始读取文件
- 每次 read 操作给出开始读文件位置
- 用一个 seek 操作设置当前位置,seek 操作后从当前位置开始顺序读文件(UNIX 和 Windows 使用该方法)
4.1.5 文件属性
文件属性(元数据):操作系统还会保存文件一些相关信息如,文件创建日期时间、文件大小、创建者、所有者。
4.1.6 文件操作
使用文件的目的是存储后方便检索。存储和操作不同的系统提供不同的操作,下面是一些常见系统调用。
- create:创建不包含数据的文件,并设置文件一些属性
- delete:删除文件,释放磁盘空间
- open:打开文件,把文件属性和磁盘地址表装入内存,便于后续调用
- close:关闭文件以释放内部表空间
4.1.7 使用文件系统调用的一个示例程序
文件描述符:打开一个文件时返回的一个小整数
看看过,不记录了
4.2 目录
文件系统通常提供『目录』或『文件夹』用于记录文件的位置,很多操作系统中目录本身也是文件
4.2.1 一级目录系统
一个目录中包含所有文件
设计简单,快速定位文件
4.2.2 层次目录系统
树形结构的目录
4.2.3 路径名
绝对路径名:从根目录到文件的路径组成,以『/』开始
工作目录(当前目录):当前工作所在的目录,每个进程都有自己的工作目录,对进程而言切换工作目录是安全的
相对路径名:不以『/』开始,前缀加上工作目录
『.』:当前目录
『…』当前目录的父亲目录(根目录还是指向根)
4.2.4 目录操作
不同系统中管理目录的系统调用差别比管理文件的系统调用差别大。下面部分系统调用
- link:链接技术,允许多个目录中出现同一个文件,增加该文件的『i 节点计数器』(记录包含该文件的目录项数),有时称为硬链接
- unlink:删除目录项,如果目标文件只出现在一个目录中,将它从文件系统中删除,否则只删除指定目录名的连接
链接文件的一种不同想法『符号链接』(软链接),通过一个文件名指向另一个文件的小文件,文件系统通过沿着路径找到最终文件名,再用源文件操作
优点是跨磁盘界限,甚至命名远程计算机文件,缺点实现不如硬链接那样有效
结合别的博客资源等我的理解大概。硬链接直接指向磁盘;软连接指向另个文件,通过另个文件访问磁盘。具体细节后面章节可能会提到。
4.3 文件系统的实现
- 文件和目录如何存储
- 磁盘空间怎么管理
- 怎么使系统有效可靠地工作
4.3.1 文件系统布局
文件系统存放在磁盘上。(毕竟换个电脑插也要有用)
多数磁盘划分成一个或多个分区,每个分区中有一个独立的文件系统。
主引导记录(MBR):磁盘的 0 号扇区,用来引导计算机
块(通过其他博客总结):文件系统中最小单元
引导块:活动分区第一个块。为统一起见,每个分区都从一个引导块开始,即使不含有可启动操作系统。
计算机被引导(应该差不多是开机)BIOS 读入并执行 MBR,MBR 确定活动分区,读入引导块,引导块中程序装载该分区中的操作系统。
超级块:包含文件系统的所有关键参数,计算机启动或文件系统首次使用时,超级块被读入内存。
4.3.2 文件的实现
文件存储实现的关键问题:记录各个文件分别用到哪些磁盘块
1. 连续分配
最简单分配方案,每个文件作为一连串连续数据块存储在磁盘上。
优点:实现简单(只需记住磁盘地址和文件块数)、读操作性能号好
缺点:磁盘会变得零碎
2. 链表分配
每个块的第一个字作为指向下一块的指针,其他部分存放数据
优点:充分利用每一个块,不会因为磁盘碎片而浪费存储空间;目录项只需存储第一块的磁盘地址。
缺点:读慢,指针占去一些字节,每个磁盘块存储数据字节不再是 2 的整数次幂,降低系统运行效率
3. 采用内存中的表进行链表分配
内存分配表(FAT):取出每个磁盘块的指针放入内存的一个表中,这表称为『内存分配表』
优点:解决了第二种的缺点
缺点:整张表需要存入内存,磁盘太大内存也需要很大。FAT 不好扩展并应用于大型磁盘 Windows 能够支持。
4. i 节点
i 节点:一种数据结构,列出文件属性和文件块的磁盘地址,给定 i 节点就能找到文件所有块。
优点:对应节点打开时,i 节点才能在内存中。通常比 FAT 所占据空间小,因为这种方法正比于打开文件,FAT 正比于磁盘大小。
问题:文件所需磁盘块数目超过 i 节点容纳数怎么办?
一种解决方法,i 节点中最后一个磁盘地址不指向数据块而是指向符加磁盘地址的磁盘块。
4.3.3 目录的实现
目录系统主要功能,把 ASCII 文件名映射成定位文件数据所需要的信息。
还有个密切相关问题,何处存放文件属性
目录项:描述文件或文件夹的属性、大小、创建时间、修改时间等
目录项列表两种实现:
- 简单实现,目录项组成目录项列表,每个文件对应一个目录项
- 对于 i 节点系统还有一种方法,文件属性存放在 i 节点中,这种方法比上面的好
怎么实现可变长度的文件名?(笔记只写最后一种)
固定目录项长度,将文件名放置在目录后面的堆中。需要对堆进行管理,而且处理文件名时缺页中断仍旧会发生。
怎么快速查找文件名?
- 线性对目录搜索一遍,慢。
- 每个目录中使用散列表(hashmap)
- 将查找结果存入高速缓存,先查询目标是否在高速缓存中
个人感觉可以整个字典树,想不到缺点。
4.3.4 共享文件
问题:B、C 共享文件,B 修改文件,C 的目录如何更新?
这里没看懂,前面看到这一直认为目录已经在内存中了,通过共享内存就同步了。
两种解决方案
- 磁盘块不列入目录,目录指向 i 节点。缺点无法全部删除,(我寻思前面讲硬链接不是说了,删完指向 i 节点的目录项才删除文件,有点迷现在。。不管了快点看。。
- 通过符号链接,符号链接需要额外的 i 节点(路径长度决定是否有额外磁盘块),优点可以跨磁盘界限
链接带来一个新问题,文件复制可能多次复制一个被链接文件。
4.3.5 日志结构文件系统
日志结构文件系统(LFS)出现原因,未来多数的磁盘访问是写操作,这样一些文件系统中使用的提前读机制,并不能获得更好的性能。
因为寻道和旋转延迟写操作慢,零碎写操作没有效率。创建 i 节点需要些操作,操作过程死机会导致文件系统严重不一致性,i 节点写操作需要快速完成。
LFS 设计成即使面对一个大部分由零碎的随机写操作组成任务,同样能够充分利用磁盘的带宽。
基本思想:将整个磁盘结构化为一个日志,每个一段时间或特殊需要,被缓存在内存的所有未决写操作被放入一个单独的段,作为日志末尾的一个领接段写入磁盘。
不知道怎么合在一起写就快,大小相同,写的迟了反而快了。。
有点没看懂算了跳过,这想法由于和现有文件系统不匹配没有广泛应用。
4.3.6 日志文件系统
日志文件系统:保存一个用于记录系统下一步将要做什么的日志,即使电脑崩溃,可以通过日志重新完成。
这个系统已被实际应用。
考虑一个问题:移除文件,在 UNIX 中需要三步完成
- 在目录中删除文件
- 释放 i 节点到空闲的节点池
- 将磁盘块归还给空闲磁盘块池
当存在系统崩溃,会造成资源浪费。不管那种在第一步执行都会有严重问题。
日志文件系统则先写一个日志项,列出要完成的动作,写入磁盘(可能从磁盘读会验证),当日志项被写入磁盘,这些操作才可以进行,操作全部成功后擦除日志项。如果途中系统崩溃,将检查日志查看是否存在未完成操作,有则继续执行。
需要写入日志的操作是『幂等』的,运行多次和运行一次效果相同。
原子事务:要么已经完成,要么完全没动(感觉书上这里用『之间』存在歧义,是这两个选项之间,还是时间层面上的之间)
4.3.7 虚拟文件系统
同一个操作系统下都会使用很多不同文件系统。
Windows将不同的文件系统拆分为不同的盘,所以不需要整合统一。
现代 UNIX 系统尝试将多种文件系统整合到一个统一的结构中。
绝大多数 UNIX 操作系统都使用『虚拟文件系统』(VFS)概念将多种文件系统统一成一个有序的结构。
下面介绍一种普遍关于 UNIX 下文件系统的描述。
POSIX:可移植操作系统接口
大概就是通过 POSIX,将多个文件系统整合多一起,然后展现给用户。
VFS 如何工作,一个例子。
系统启动,根文件系统在 VFS 中注册,装载其他文件系统时,它们也必须在 VFS 中注册。注册就是提供 VFS 需要的信息,装载文件系统后就可以使用了。
4.4 文件系统管理和优化
4.4.1 磁盘空间管理
几乎所有文件系统都把文件分割成固定大小的块存储,块之间不一定相邻。
1. 块大小
块大小应该是多少?块大浪费空间,块小降低性能。
根据调查,详细数据不放了。小文件多,但是大文件占据了大多数磁盘。
算了跟我没什么关系。
2. 记录空闲块
两种方法被广泛采用。
- 磁盘块链表,用空闲块存放空闲表。
- 位图,n 个块的磁盘用 n 位位图,用 0/1 表示状态。如果空闲块趋近于连续,也可以记录连续分块状态,而不是单个分块状态。
空闲表(应该是说内存里的,上面两个应该是磁盘里的),只需内存中保存一个指针块。创建文件取出指针,删除文件添加指针,指针不够读入指针。
某些情况产生不必要的磁盘 I/O。一个解决方法,指针块满了不是将全部指针写入,而是写入一半。
对于位图,在内存中只保留一个块是有可能的。通过位图在单一块上处理还有符加好处,磁盘块紧密,减少磁盘臂移动。
3. 磁盘配额
多用户操作系统中,防止有人占用太多磁盘空间。
4.4.2 文件系统备份
人们往往使用『增量转储模式』
海量数据可以压缩,但是磁盘上单个坏点就能破坏解压缩算法。
修改转储算法,记下文件系统的瞬时快照,复制关键的数据结构,然后需要把将来对文件和目录的修改复制到块中。留待空闲时再备份
越看越觉得和我关系不大跳
4.4.3 文件系统的一致性
系统崩溃可能会产生文件系统处于不一致状态。(不是有日志文件系统了吗。。)
接下来介绍 UNIX 的 fsck 程序。系统崩溃后重新启动可以运行该程序。
所有文件系统检验程序可以独立地检验每个文件系统(磁盘分区)的一致性。
一致性检查分为两种:『块的一致性检查』和『文件的一致性检查』
容我先跳过此节QWQ。
4.4.4 文件系统性能
访问磁盘慢,需要优化
1. 高速缓存
缓冲区高速缓存(块高速缓存):用来减少磁盘访问次数。
本书中,高速缓存指一系列块,逻辑属于磁盘,被保存在内存中。
管理高速缓存有不同的算法,常见算法:检查全部读请求,查看高速缓存中是否有需要块,存在无须访问磁盘,不存在读到高速缓存再复制到需要的地方。
需要一种快速判断所需块是否存在的方法,比如 hashmap
如果高速缓存已满,与分页置换类似。
一个问题,高速缓存如果很久才放回磁盘中,更容易出现修改数据未保存系统崩溃后数据丢失。
UNIX 中有个系统调用 sync,强制把全部修改过的块立即写入磁盘。系统启动时后台运行一个通常名为 update 的程序每隔一段时间调用一次 sync。
Windows,有个等价 sync 的系统调用 FlushFileBuffers,不过区别有如果高速缓存中有块被修改立即写回磁盘。
2. 块提前读
顺序读取文件,可以提前将块写入高速缓存
3. 减少磁盘臂运动
输出文件让输出的块更接近,读的时候磁盘臂运动少点。
磁盘中部存放 i 节点,减少平均寻道时间。
算了这部分看看也没必要笔记感觉。
4.4.5 磁盘碎片整理
通过移动文件,整理磁盘随便释放一个连续的块空间。
4.5 文件系统实例
4.5.1 MS-DOS
4.5.2 UNIX V7 文件系统
第十章讨论更新的 UNIX 文件系统。看了一眼不做笔记
4.5.3 CD-ROM 文件系统
应该就是光盘,一次性的写。放弃看还挺长。
4.6 有关文件系统的研究
4.7 小结
文件系统是一组文件和目录,以及对文件和目录的操作。
文件系统设计者需要考虑:
- 存储区如何分配
- 系统如何记录哪个块分给了哪个文件:i 节点等
- 磁盘空间管理:空闲表等
- 文件系统可靠性:日志文件系统等
- 文件系统性能:高速缓存、预读取等