文章目录
12.1 文件系统概念
12.1.1 文件系统基本概念
文件系统:操作系统中管理持久性数据的子系统,提供数据存储和访问功能
- 组织、检索、读写访问功能
- 大多数计算机系统都有文件系统
- Google也是一个文件系统
文件:具有符号名,由字节序列构成的数据项集合。
- 文件系统的基本数据单位
- 文件名是文件的表示符号
文件系统的功能
- 分配文件磁盘空间
- 管理文件块(位置和顺序)
- 管理空闲空间(位置)
- 分配算法(策略)
- 管理文件集合:
- 查找:文件及其内容
- 命名:通过标识符进行定位
- 文件系统结构:文件的组织方式
- 数据可靠和安全
- 可靠:持久保存文件,避免错误和崩溃
- 安全:多层次保护数据安全,减少攻击危害
文件的属性包括:名称、类型、位置、大小、保护、创建者、创建时间、最近修改时间等
文件头:文件系统元数据中的文件信息
- 文件属性
- 文件存储位置和顺序
12.1.2 文件系统种类
- 磁盘文件系统:文件存储在数据存储设备上,如磁盘
- 例如FAT,NTFS,ext2/3,ISO9660
- 不同文件系统的安全要求不同,按照所需选取对应协议即可。
- 数据库文件系统:
- 文件特征是可被寻址(辨识)的
- 例如WinFS
- 日志文件系统:
- 记录文件系统的修改/事件
- 网络/分布式文件系统
- 例如:NFS,SMB,AFS,GFS
- 特殊文件系统,如管道
- 虚拟文件系统
关于网络/分布式文件系统
文件可以通过网络被共享
- 文件位于远程服务器,客户端
- 客户端远程挂载服务器文件系统
- 标准系统文件访问被转换成远程访问
- 标准文件共享协议:NFS(UNIX),CIFS(Win)
分布式文件系统的挑战:
- 客户端和客户端上的用户辨识很复杂
- 比如NFS是不安全的
- 一致性问题
- 错误处理模式
12.2 文件组织和存储
12.2.1 虚拟文件系统,目录和别名
文件系统基本数据结构包括:
- 文件卷控制块:每个文件系统一个,包括文件系统的详细信息如块、块大小、空余快、计数、指针等,如Unix中的superblock
- 文件控制块:每个文件一个,包括文件的详细信息如访问权限、拥有者、大小、数据块位置等,如Unix中的vnode
- 目录项:每个目录项一个(目录和文件),将目录项数据结构以及树形布局编码成数据结构,指向文件控制块、父目录、子目录。
持久存入外存,当需要加载时进入内存:
- 卷控制模块:当文件系统挂载时进入内存
- 文件控制块:当文件被访问时进入内存
- 目录节点:在遍历一个文件路径时进入内存
文件以目录的方式组织起来。
目录是一种特殊的文件,内容是文件索引表。
现有的文件目录是树形,对于一直使用Windows的用户来说,这一点应当不难理解。
这利用虚拟文件系统的方式,将树形逻辑和线性的物理地址空间联系在一起。
目的:对所有不同文件系统的抽象
功能:
- 提供相同的文件和文件系统接口
- 管理所有文件和文件系统相关联的数据结构
- 高效查询例程,遍历文件系统
- 与特定文件系统模块的交互
典型目录操作:搜索、创建、删除、列出、重命名、遍历
操作系统应该只允许内核修改目录:
- 确保映射的完整性
- 应用程序通过系统调用访问目录
目录可以通过线性表或者哈希表实现。
文件别名:使用两个或多个文件名关联同一个文件
- 硬链接:多个文件项指向同一个文件,各个链接平等,删除掉最后一个文件项之后才删除文件本身。
- 软链接:以“快捷方式”指向其他文件,通过存储真实文件的逻辑名称来实现。
文件目录中的循环的避免:
- 只允许到文件的链接,不允许在子目录的链接
- 增加链接时,用循环检测算法确定是否合理
- 遍历时限制遍历层数,也可以防止循环带来的危害
名字解析(路径遍历):
名字解析:把逻辑名字转换成物理资源(如文件)
- 依据路径名,在文件系统中找到实际文件位置
- 遍历文件目录,知道找到目标文件
举例:/bin/ls
- 读取根目录的文件头(在磁盘固定位置)
- 读取根目录的数据块,搜索“bin”项
- 读取bin的文件头
- 读取bin的数据块,搜索ls项
- 读取ls的文件头
当前工作目录(pwd):每个进程都会指向一个文件目录用于解析文件名。
允许用户指定相对路径来代替绝对路径,如用$PWD
可以替代当前目录/bin
。
文件系统挂载
- 文件系统需要挂载才能访问
- 未挂载的文件系统挂载在挂载点上,如下图
WSL就是将Windows的文件系统挂载到/mnt目录。
12.2.2 文件分配
背景:大多数文件都很小,一些文件非常大
- 需要对小文件提供很好的支持,块空间不能太大
- 必须支持大文件,大文件访问必须高效
如何表示分配给一个文件数据块的位置和顺序就成为一个问题。
分配方式主要有如下几种:
- 连续分配
- 链式分配
- 索引分配
以下我们从存储效率和读写性能等方面来评定这些分配方式。
连续分配
- 文件头指定起始块和长度
- 分配策略包括最先匹配、最佳匹配
- 优点:文件读取表现好,访问高效。
- 缺点:碎片;文件增长
链式分配
- 文件以数据块链表方式存储
- 文件头包含了到第一块和最后一块的指针
- 优点:创建、增大、缩小很方便,没有碎片
- 缺点:访问效率低,可靠性差
索引分配
- 为每个文件创建一个索引数据块,指向文件数据块的指针列表
- 文件头包含了索引数据块指针
- 优点:直接访问,创增缩很方便,没有碎片
- 缺点:对于小文件来说,有多余开销;多索引块才能实现大文件索引
大文件可以使用链式索引或者多级索引实现。
UFS多级索引分配
文件头包含13个指针
- 10个指针指向数据块
- 第11个指针指向索引块
- 第12个指针指向二级索引块
- 第13个指针指向三级索引块
效果
- 提高了文件大小限制阈值
- 动态分配数据块,文件扩展很容易
- 小文件开销小
- 只为大文件分配间接数据块,大文件在访问数据块时需要大量查询
12.2.3 空闲空间管理
采用什么数据结构来表示空闲空间?
位图:用一个01向量来表示整个存储空间的数据块占用情况。0表示空闲,1表示已经分配
使用简单,但是会产生一个很大的向量
- 维护起来工作量很大
- 假定空闲空间在磁盘中均匀分布,则找到空闲块之前平均扫描n/r个bit
类似空间分配、页式存储等的思路,这里可以使用链表串联空闲空间。
另外可以结合索引结构,实现索引链表,节省空间且容易查找
12.2.4 RAID
通常磁盘通过分区来最大限度减小寻道时间
-
分区是一组柱面的集合
-
每个分区都可以视为逻辑上独立的磁盘
一个拥有完整文件系统实例的外存空间通常常驻在磁盘的单个分区上。 -
可以将一个磁盘分为多个逻辑分区。
-
也可以将多个磁盘组成一个逻辑分区
使用多个磁盘的好处:
- 通过并行改善吞吐量
- 通过冗余改善可靠性和可用性
冗余磁盘阵列(RAID)
- 多种磁盘管理技术
- RAID分类:RAID-0,RAID-1,RAID-5等
- 实现:可以通过操作系统内核的文件管理实现,也可以通过RAID硬件控制器
RAID-0:磁盘条带化
- 把数据块分成多个子块,存储在独立的磁盘中
- 通过独立磁盘上并行数据块访问提供更大的磁盘带宽
RAID-1:磁盘镜像
- 向两个磁盘写入,从任意一个读取
- 可靠性成倍增长,读取性能线性增加
RAID-4:带校验的磁盘条带化
- 数据块级的磁盘条带化+专用奇偶校验磁盘
- 允许从任意一个故障磁盘中恢复,增大可靠性
RAID-5:带分布式校验的磁盘条带化
减小对校验和所在磁盘的读写压力
RAID-3:如上的RAID-0,4,5基于数据块,也可以有基于位的条带化/校验结构。
RAID-6:增加一个奇偶校验块,容许更多的出错。
RAID嵌套
12.3 文件访问
12.3.1 文件描述符
这一节叙述文件描述符,并因此简单了解文件的内部组织形式和简单的访问问题。
文件描述符:操作系统在打开文件表中维护的打开文件
- 文件指针:最近一次读写位置,每个进程分别维护自己的打开文件指针
- 文件打开计数:当前打开文件的次数,最后一个进程关闭文件时,将其从打开文件列表中去除。
- 文件的磁盘位置:缓存数据访问信息
- 访问权限:每个进程的文件访问模式信息
文件的用户视图:持久的数据结构
系统视图:
字节序列的集合(Unix),系统不关心存储在磁盘上的数据结构
- 数据块的集合
- 数据块是逻辑存储单元,扇区是物理存储单元
- 块大小<>扇区大小(中间的符号表示两者可能不一样)
用户视图到系统视图的转换
进程读文件:
- 获取字节所在的数据块
- 返回数据块内对应部分
进程写文件:
- 获取数据块
- 修改数据块中对应部分
- 写回数据块
文件系统中的基本操作单位是数据块
例如,getc和putc即使每次只访问1字节数据,也需要缓存目标数据4kB
访问模式
- 顺序访问:大多数文件访问的方法
- 随机访问:从中间读写,不常用但重要,比如虚存中把内存页存储在文件
- 索引访问:依据数据特征建立索引,通常操作系统不完整提供索引访问,数据库是建立在索引内容的磁盘访问
文件内部结构 - 无结构:单词、字节序列
- 简单记录结构:分列、固定长度、可变长度
- 复杂结构(比如MS Word)
文件共享和访问控制
多用户系统中的文件共享是非常必要的
访问控制:
- 每个用户能够获得哪些文件的哪些访问权限
- 访问模式:读写、执行、删除、列表等
文件访问控制列表(ACL):<文件实体,权限>
Unix模式:<用户|组|所有人,读|写|可执行>
语义一致性:规定多进程如何同时访问共享文件
- 与同步算法相似
- 因磁盘IO和网络延迟而设计简单
UFS(Unix文件系统)语义:
- 对打开文件的写入内容立即对其他打开同一文件的其他用户可见
- 共享文件指针允许多用户同时读取和写入文件
会话语义:写入内容只有当文件关闭时可见
读写锁:一些操作系统和文件系统提供该功能
12.3.2 文件缓存和打开
多种磁盘缓存所在系统硬件的位置:
首先介绍数据块缓存:
数据块按需读入内存
- 提供read操作
- 预读机制:预先读取后面的数据块
数据块使用之后会被缓存
- 假设数据将会再次用到
- 写操作可能被缓存和延迟写入
两种数据块缓存方式 - 数据块缓存
- 页缓存:统一缓存数据块和内存页
页缓存
相对于虚拟页式存储的“时间换空间”,这里用空间换时间,将I/O换成内存访问,将上图中的虚拟页对换和文件读写直接统一为页缓存
问题:
- 可能导致缺页,脏页的设置
- 页置换算法需要协调虚拟存储和页缓存间的页面数
文件系统中打开文件的数据结构,除了之前提到的文件描述符,还要维护一个打开文件表。
- 每个进程一个进程打开文件表
- 一个系统级的打开文件表
- 有文件被打开时,文件卷就不能被卸载
从上图中也可以看出,多个进程打开文件可能会产生不一致的冲突,我们这里有打开文件锁的机制。
- 强制:根据锁保持情况和访问需求,确定是否拒绝访问
- 劝告:进程可以查找锁的状态来决定怎么做