第四章 文件系统
4.1 文件
从用户
角度来考察文件
。用户如何使用文件
,文件
有那些特性。
4.1.1 文件命名
文件
一种抽象机制,提供了一种在磁盘上保留信息而且以后方便读取的方法。
-
有的文件系统区分大小写,有的则不区分
Unix
是前者,MS-DOS
是后者
-
FAT-16
,FAT-32
,NTFS
。FAT-16(File Allocation Table,文件配置表)
: Windows 95FAT-32
: Windows 98NTFS(New Technology File System,新技术文件系统)
:之后所有Win系列的文件系统
4.1.2 文件结构
文件
可以有很多构造方式,列出常用的三种方式。
-
字节序列
- 操作系统所见的就是字节,任何含义只在用户程序中解释。
Unix
和Winodws
都是用这种方式。
-
记录序列
-
读和写都是以
记录
为单位 -
80
列的穿孔卡片
还是主流的时候。80
个字符 = 一个记录。
-
现在已经没有这种方式了。
-
-
树
- 类似与
map
,key-value
对,并利用平衡树
来维护key
值。- 以便能快速查找
key
值。
- 以便能快速查找
- 在一些处理商业系统的大型计算机受到欢迎
- 类似与
4.1.3 文件类型
普通文件(regulr file):包含用户的信息
ASCII
文件-
由多行正文组成
Unix
系统每行以换行符(/n
)结束。Win
系统采用回车符(/r
)和换行符(/n
)。
-
优势
- 可以显示和打印,可以用文本编辑器编辑。
- 作为其他程序的输入或输出。
-
二进制
文件- 具有一定的内部结构,使用该文件的程序才了解这种结构。
目录(directory):管理文件系统结构的系统文件。
4.1.4 文件存取
-
顺序存取(sequential access)
- 早期操作系统只有这一种方式。
- 比如你要读
adsadasdsaxdas
中第7位,必须从头开始找到第7位。 - 效率极低,但是适合
磁带
的工作方式。现在已被淘汰。
- 比如你要读
- 早期操作系统只有这一种方式。
-
随机存取文件(random access file)
- 能够以任何次序读取其中字节或记录的文件。
- 两种方式指示从哪里读取文件。
- 第一种::
read
操作中给出开始读文件的位置。 - 第二种 : 维护一个
文件位置
。利用seek
设置。
- 第一种::
4.1.5 文件属性
与文件相关的信息,如创建日期,大小等。这些信息称为文件属性(attribute)
,有些人称之为元数据(metadata)
。
- 前4个属性与文件保护相关。
- 标志位
- 时间字段
- 大小字段
4.1.6 文件操作
-
creat
-
delete
-
open
- 把文件属性和磁盘地址表装入内存。
-
close
- 关闭文件释放内部表空间。
-
read
-
write
-
append
-
seek
-
get attributes
-
set attributes
-
rename
4.1.7 使用文件系统调用的示例程序。
完成了copyfile abc xyz
的操作
4.2 目录
目录本身也是文件
。
4.2.1 一级目录系统
目录系统
最简单形式就是一个目录包含所有的文件。
- 诸如电话,数码相机以及一些便携式音乐播放器使用
4.2.2 层次目录系统
4.2.3 路径名
-
绝对路径
- 一定以
分隔符
开头- WIN:
- Unix:
/
- MULTICS:
>
- WIN:
- 一定以
-
相对路径
- 必须要和
工作目录
一起使用。 - 几个特殊的符号
.
: 当前目录..
:上一层目录~
:Linux
中自己用户的根目录~user
:Linux
中user
的根目录-
:Linux
中上一次最近访问的目录
- 必须要和
4.2.4 目录操作
-
creat
-
delete
-
opendir
-
closedir
-
readdir
-
rename
-
link
- 连接技术允许在多个目录出现同一文件。
- 增加该文件的
i节点
计数器的个数(记录含有该文件的目录树目)。 - 有时称为
硬连接(hard link)
。硬链接
不占用磁盘空间硬链接
只能作用于文件,不可跨越分区。硬链接
和原来的文件没有什么区别,而且共享一个 inode 号。硬连接
是完全平等的,都掌控的真实的,而不是一个快捷方式。
-
unlink
- 删除连接文件。
- 在
Unix
中,用于删除文件的系统调用实际上就是unlink
-
符号连接
: 类似于快捷方式,又叫软连接
- 可以跨越磁盘的界限
- 速度较慢
4.3 文件系统的实现
实现者的角度考察文件
。
4.3.1 文件系统布局
文件系统存放在磁盘
上
-
多数磁盘被划分为一个或多个
分区
。- 每个
分区
都有独立的文件系统。
- 每个
-
磁盘的
0号扇区
称为主引导记录(Master Boot Record,MBR)
,用来引导计算机。 -
MBR
的结尾是分区表
。- 该表给出了每个分区的起始和结束地址。
- 表中的一个分区被标记为
活动分区
。
在计算机被引导
的时候
BIOS
读入并执行MBR
。MBR
做的第一件事是确定活动分区
,读入它的第一个块,叫做引导块(boot block)
,并执行之。引导块
中的程序将装载该分区中的操作系统
。- 为了统一起见,所有
分区
的开始都是引导块
,即使没有操作系统。
- 为了统一起见,所有
之后的磁盘分区的布局随着文件系统
的不同而变化。以上是一个可能的布局。
-
第一个是
超级块(superblokc)
-
超级块
包含文件系统的所有关键参数。- 确定文件类型用的
魔数
。 - 文件系统数据块的数量。
- 其他重要管理信息。
- 确定文件类型用的
-
计算机启动,或文件系统首次使用时,
超级块
被读入内存。
-
-
文件系统空闲块的信息。
- 可以用位图或指针列表给出。
-
可能有
i节点
- 是一个数据结构数组,每个
文件
一个。 i节点
说明了文件的方方面面。
- 是一个数据结构数组,每个
-
根目录
-
文件和目录
4.3.2 文件的实现
文件存储实现的关键问题
- 记录各个文件分别使用那些磁盘块
1.连续分配
跟malloc
的动态存储分配是一模一样的模型。(但是malloc
可以忽视这几个缺点)
优点:
-
实现简单
- 只需记录文件的磁盘地址和文件的块数
-
读性能好
- 只需一次查找,之后不需要
寻道
和旋转
延迟。 - 数据以磁盘全带宽的速率输入。
- 只需一次查找,之后不需要
缺点:
-
外部碎片太多,需要维护一个空闲列表来存储文件。
-
但是为了能在空闲列表中找到一个合适的块
必须要知道文件最终的大小。
-
-
大多数时候对于
文本文档
不知道文件的最终大小,所以这是一个硬伤。
使用场景
-
存在这种情形,文件的大小都事先知道,后续使用中,也不会被改变
CD-ROM
文件系统。 -
DVD
的文件系统
多年前,连续分配由于其简单和高性能被实际用于在磁盘文件系统中,后来由于讨厌在文件创建时不得不指定最终文件的大小,这个想法被放弃了。但是随着
CD-ROM
,DVD
以及其他一次性写光学介质的出现,突然间连续分配又成为了一个好主意。所以研究具有清晰和简洁概念的老式系统和思想是很重要的,因为它们有可能以一种令人吃惊的方式在未来系统中得到使用。
2.链表分配
优点:
- 充分利用了每个磁盘块。
- 也只需要存放首地址
缺点
- 随机读的复杂度是
O(n)
,太慢。 - 指针占去了一些字节,使得存储数据的字节数不再是
2的整数次幂
。-
程序都是以
2的整数次幂
来读写磁盘块,要读一个完整的块,可能要两个磁盘块拼接。使得速度变慢
-
- 在内存中采用表的链表分配
取出每个磁盘的指针字,把它放到内存的一个表中。这个表叫做文件分配表(File Allocation Table,FAT)
.
优点:
- 解决上述链表的两个缺点。
- 对于随机读写,因为在内存中,即使
O(n)
也是可以接受的。 - 存储数据是
2的整数次幂
了。
- 对于随机读写,因为在内存中,即使
缺点:
-
对于
200GB
的磁盘和1KB
大小的块,这张表需要2亿项
,每个表项4字节
。这张表要占
600
到800MB
的内存,不太实用 -
所以
FAT
对于大磁盘不适用
- i结点
每个文件赋予一个称为i节点(index-node)
的数据结构
- 其中列出
文件属性
和文件块的磁盘地址
优势
-
只有在文件打开的时候,
i节点
才载入内存。- 与磁盘总大小无关,只与打开的文件有关。
-
类似虚拟地址空间的
多级页表
的方式。i节点
里的地址就是一级页表
。最底层的地址
才是实际的磁盘地址
。- 便于
索引
,节约空间,完美。
缺点:貌似没有
4.3.3 目录的实现
目录项
打开文件,操作系统利用用户给出的路径名找到相应目录项
。
-
目录项
提供了查找文件磁盘块所需要的信息。- 因系统而异
- 有可能是磁盘地址+长度(对于连续分配)
- 有可能是第一块的地址(对于链表来说)
i节点号
- 因系统而异
-
无论如何,目录系统的主要功能是把
ASCII
文件名映射成定位文件数据
所需的信息。
文件属性
与此密切相关的问题是在何处存放文件属性
。
- 一种显而易见的方法是把
文件属性
直接存放在目录项中。(对应于Windows
) - 对于采用
i节点
的系统,还可以把文件属性
存到i节点
中,而不是目录项中。
文件长度
现代操作系统都支持可变长度
的长文件名,它们是如何实现的。
- 第一种,最简单的固定一个255字节的文件名,很浪费空间不考虑。
- 第二种,就是
图4-15(a)
,被后面那种完爆就不提了。 - 第三种,利用
堆
来维护文件名。- 每个目录项自身都有固定长度。
堆
的维护跟malloc
的类似。- 缺点
-
一个目录项可能会分布在多个页面里。
因此处理文件名还是可能有页面故障。
-
查找文件名
-
利用哈希表
- 我的老本行就不要介绍了。
-
利用高速缓存
4.3.4 共享文件
文件系统本身是一个有向无环图(DAG)
而不是一棵树。
有种方式共享(连接
)
-
硬链接
-
目录指向
i节点
,并计数 -
只有当计数被置为0的时候,才真正被删除。
-
-
软连接(符号连接)
-
创建一个类型为
LINK
的文件,并把该文件放在B下。- 里面存储了实际的 连接文件位置
-
访问文件,需要额外的开销
-
复制时的问题
如果允许复制时不保留连接的话 (cp 没有-d
)
-
软连接,直接复制所指向文件本身。
-
硬链接,复制过来后,重置
i-node
的计数器。
4.3.5 日志结构文件系统(看不下去了,翻译的太烂了)
日志结构文件系统(Log-structured File System,LFS)
设计的主要原因是
- CPU的运行速度越来越快,RAM内存容量变得更大,磁盘高速缓存也在增加。
- 不需要磁盘访问操作,就能完成很大一部分读请求。
- 未来多数的磁盘访问操作是写操作。
- 写操作往往是零碎的。
- 一个
50us
的磁道写操作需要10ms
的寻道和4ms
的旋转延迟操作。磁盘的效率降低到1%
。
零碎的写操作来源于哪里?假设写入一个新建的文件
。
- 写该文件目录的
i
节点,目录块。 - 文件的
i
节点,以及文件本身。
这些写操作很慢,如果在写操作完成之前死机。
- 造成文件系统的严重不一致性。
4.3.6 日志文件系统
保存一个用于记录系统下一步将要做什么的日志
。
-
即使奔溃后,也能通过
日志
来继续处理。 -
微软的
NTFS
,ext3
和ReiserFS
文件系统都是用日志。
4.3.7 虚拟文件系统(翻译太烂,看不完)
即使在同一计算机下同一操作系统,也会使用不同的文件系统。
Windows
Windows
通过指定不同的盘符来处理这些不同的文件系统,比如C:
,D:
等。
盘符是显示存在的,所以Windows
知道传递什么样的文件系统请求。
不需要将不同类型文件整合同一模式。
Unix
相比下,所有现代的UNIX
系统做了一个很认真的尝试,将多个文件系统整合到一个统一的结构中。
觉得大多数UNIX
操作系统使用虚拟文件系统(Virtual File System,VFS)
来将文件系统统一。
4.4 文件系统管理和优化
4.4.1 磁盘空间管理
几乎所有的文件系统都把文件
分割成固定大小的块
来存储,各块之间不一定相邻(页式管理
)。
块大小
一旦确定把文件按固定大小的块来存储,就会出现一个问题,块的大小应该是多少?
过大的块(空间利用低
)
- 小的文件浪费大量磁盘空间,
内部碎片
严重。
过小的块(时间利用低
)
- 大多数文件都会要有多个块,需要多次
寻道
和旋转
延迟才能读完这个文件,性能太低。
观点
-
从历史观点来说,文件系统将大小设在
1~4KB
之间。(历史时期磁盘数量少,空间利用率更重要)。 -
随着磁盘超过1TB,可以通过将块的大小提升到
64KB
接收磁盘的浪费,增加时间性能。- 现代基本不可能出现磁盘空间短缺的状况。
记录空闲块
-
磁盘块链表
- 通常情况下,采用
空闲块
来存放空闲表
。 内存
中保存一个指针块
- 文件创建时,所需要的块从执政块中取出来。
- 如果指针块用完了,从磁盘读入一个新的指针块。
- 文件删除是,其磁盘块被释放,并添加到
指针块
。- 指针块填满后,将它写入磁盘。
- 避免不必要的
I/O
,(即有利于创建,也有利于写)- 在内存中保留一个
半满
的指针块,其余大多数为满
的状态
- 在内存中保留一个
- 文件创建时,所需要的块从执政块中取出来。
- 通常情况下,采用
-
位图
-
n
个块的磁盘需要n位位图
。- 空闲块用
1
表示 - 已分配块用
0
表示
- 空闲块用
-
位图所需要的空间很少。
-
隐形好处,保证很有可能存储会比较紧密,减少磁盘壁的移动。
-
缓存
-
由于位图是一种固定大小的数据结构,在支持分页的
内核
里可以直接存放到虚拟地址空间,等待需要的时候进行
页面的调入
。
-
-
磁盘配额
现在应该没人用这个技术了。。。
4.4.2 文件系统的备份(略过)
几个问题
- 一:备份那些数据?
- 二:对前一次已经备份过但没有修改过的再备份十分浪费。
- 三:是否压缩?
- 四:对还在活动的文件系统做备份是很难得。
- 五:备份会引入非技术问题(间谍?)
4.4.3 文件系统的一致性
影响文件系统的可靠性的另一个问题是文件系统的一致性
。
- 修改过的磁盘块全部写回之前系统崩溃,可能使文件系统处于
不一致状态
。
为了解决文件系统的不一致问题,很多计算机都带有一个实用程序以检验文件系统的一致性。
Unix
的fsck
,Windows
的scandisk
.- 一般在崩溃重启后,都可以选择性运行。
我们介绍一下Unix
的fsck
的原理。
- 块的一致性检查
- 文件的一致性检查
4.4.4 文件系统性能
-
高速缓存
- 块高速缓存
- 缓冲区高速缓存
- 存储器映射
-
块提前读
- 只能加速
顺序存取方式
- 对
随机存取方式
,效率更低。
- 只能加速
-
减少磁盘臂运动
-
空闲块
的分配减少磁盘臂运动- 使用位图
- 空闲表使用块簇技术。
-
i
节点的优化-
读取一个很短的文件,也需要先两次磁盘访问
- 读取
i
节点 - 读取访问块
- 两者之间的访问增加寻道时间。
- 读取
-
改进
- 第一种。磁盘中部存放
i
节点。 - 第二种。磁盘分为多个
柱面组
,每个柱面组有自己的i节点
。
- 第一种。磁盘中部存放
-
-
4.4.5 磁盘块整理
Win
磁盘性能可以这样恢复
- 移动文件使它们相邻,把所有的空闲空间放在一个或多个大的连续空间。
windows
的defrag
从事这个事windows
用户应该定期使用。NTFS
貌似产生的碎片少很多了
Linux
- Linux文件系统(
ext2
,ext3
)由于使用i节点
的方式,很少需要使用手动的磁盘碎片整理。
4.5 文件系统实例
4.5.1 CD-ROM
4.5.2 MS-DOS
FAT
和FAT32
现在依旧流行于嵌入式系统。
读文件时
MS-DOS
调用open
系统调用,获得文件的句柄
。-
open
系统调用识别一个路径。路径是一个一个分量的查找直到找到最终的目录读入内存,搜索要打开的文件。
-
目录项
4.5.3 Unix V7
即便是早期版本的UNIX
也是一个相当复杂的多用户文件系统,因为它是MULTICS
继承下来的。