文件管理
引入:
- 核心:屏蔽底层不同存储介质的异构性
- 每种存储介质的 基本存储单元 显然是不同的 (磁盘、磁带、光盘…)
- 每台计算机显然可以同时拥有这些不同的存储介质
- 操作系统为了统一管理不同的存储介质的存储而提出了 文件 的这种抽象的概念
- 解释1:无论具体的存储介质是如何实现的,操作系统都只会认为这种存储介质的基本存储单元是文件而不是其他的
- 解释2:操作系统如果不提供 文件 这种抽象概念,那么显然操作系统需要为每种介质单独提供管理的实现,显然是非常麻烦的
组成:
文件管理系统分为两个组成部分:==文件接口设计== & ==文件接口实现==
文件接口实现分为两个组成部分:==文件集合== & ==目录结构==
文件系统接口
概念
定义:
-
注:数据仅能够通过 文件这种抽象接口 才可以写到外存中
组成:数据 + 程序
-
- 名称:(1) 以人类的可读形式保存的 唯一 信息 (2) 名称 是否区分大小 写取决于操作系统的具体实现 (Window 不区分大小写 )
- 标识符:操作系统用于识别每个文件的 唯一 符号
- 类型:扩展名 (可以指明文件内部结构)
- 尺寸:文件当前的大小 (文件的 实际占用空间 会比文件自身要大)
- 访问:用户对于文件读写和执行的 权限
- 时间 & 日期:文件被创建或者被修改的时间
-
创建文件:
系统调用参数:文件空间大小 + 文件存放路径名 + 文件名称
系统实际行为:(1) 磁盘 中为文件 分配空间 (2) 目录结构中创建相应的 文件条目
读文件:
- 系统调用参数:文件名称 + 读入数据大小 + 读入数据存放的内存地址
- 系统实际行为:(1) 使用 文件名称 在目录中搜索其在 磁盘的位置 (2) 将文件加载到指定的内存地址中 (3) 文件读指针 指向文件中的第一条数据
写文件:
系统调用参数:文件名称 + 写入数据大小 + 写入数据存放在文件中的地址
系统实际行为:(1) 使用 文件名称 在目录中搜索其在 磁盘的位置 (2) 文件写指针 移动到需要写入的位置 (3) 根据文件写指针指向的位置写入数据
重定位文件:(?)
- 系统调用参数:文件地址
- 系统实际行为:将当前文件指针指向新的文件地址
删除文件:
- 系统调用参数:文件名称
- 系统实际行为:(1) 使用 文件名称 在目录中搜索其在 磁盘的位置 (2) 先 释放文件在磁盘中占用的空间 (3) 再 删除目录中相应的文件条目
截断文件
- 系统调用参数
- 系统实际行为:(1) 使用 文件名称 在目录中搜索其在 磁盘的位置 (2) 仅释放文件在磁盘中占用的空间,并不删除目录中对应的文件条目 (保留文件的结构仅删除信息)
注意点:上述 6 个文件操作仅组成了文件操作的最小集合,实际的文件操作并不只有这些
打开文件表:
引入:
- 上述所有的文件操作几乎都涉及搜索文件在磁盘中的位置
- 为了简化这个重复搜索的操作,要求每次对文件操作之前都应该执行打开文件的操作
- 被打开的文件的属性都会被打开文件表记录
定义:(1) 维护所有打开文件的属性 (2) 每个打开文件都与一个索引映射 (便于其余文件操作可以快速找到文件而不用搜索)
分类:
系统打开文件表:==文件磁盘地址 + 文件访问权限 + 文件打开计数== (记录当前打开此文件的进程数量)
进程打开文件表:==文件指针== :进程使用文件指针访问系统打开文件表并且操作文件
问题:为什么需要系统打开文件表和进程打开文件表?
- 多个进程可以同时打开同一个文件并且各自对其进行操作,每个进程对文件的操作不同显然文件指针不应该是共享的
- 文件指针如果保存在系统打开文件表中,那么想要实现文件指针独立,那么多个进程打开同一个文件需要非常多重复的映射关系
- 为此只能够将文件指针独立存放在进程打开文件表中,而系统打开文件表中仅存放文件相关信息
文件锁
引入:多个进程可以同时打开同一文件并对其进行操作显然就很容易造成数据的不一致性
锁类型:
- 共享锁:多个进程可以同时获取共享锁:允许多个进程同时对文件进行读取操作
- 独占锁:仅有一个进程可以获取独占锁:仅允许一个进程对文件进行写入操作
锁机制:
强制文件锁定机制:文件的独占锁已经被进程获取时,其余想要访问该文件的进程都会被操作系统禁止
建议文件锁定机制:文件的独占锁已经被进程获取时,操作系统不会禁止访问,而是由开发人员自行控制锁的获取和释放
注:控制不当显然是会造成死锁的
细节:
- Windows 采用的是强制文件锁定 & UNIX 采用的是建议文件锁定机制
- 文件锁 & 同步:文件锁显然仅能够用于文件,而同步机制是对任何计算机资源都适用
访问
定义:对文件内部数据的访问方式
顺序访问:
- 内容:对文件中的数据按顺序加以处理
- 特点:目前最常见的文件访问方式
直接访问(随机访问)
内容:文件由固定长度的逻辑记录 (块) 组成,以方便进程按任意顺序读取或者写入文件
特点:
每个逻辑记录 (块) 都有自己的编号:用户提供的编号是 逻辑块号,操作系统访问的是 物理块号 (和内存管理的逻辑地址和物理地址类似)
-
(1) 数据库软件运行在操作系统上并且存储的数据是文件形式保存
(2) 所以直接访问本质还是顺序访问:因为大多数操作系统只能够进行顺序访问,需要进行复杂的操作来实现直接访问
索引访问:
- 内容:建立索引表结构保存 块号 - 块地址 的映射关系
- 特点:
- 索引访问时建立在直接访问的基础之上
- 数据库通常采用索引以加快搜索的速度:索引访问本质则是使用 额外的空间 保存块地址和块号的映射关系而不再是顺序访问
问题:为什么操作系统不采用直接访问的方式去访问文件呢?
细节:
- 文件内部数据的 访问方式 取决于文件内容的 存储方式
- 文件内部数据太大时会导致索引表也很大:通常会使用 多级索引 来解决这个问题
目录
概念
定义:包含所有 ==文件控制块(FCB)== 的有序集合
文件控制块 (FCB):
定义:每个文件都拥有的一个 保存文件所有相关信息的数据结构
内容:文件名 + 文件存放的物理地址 + 访问权限 +···
操作:(1) 搜索文件 (2) 创建文件 (3) 删除文件 (4) 遍历目录 (5) 遍历文件系统 (就是遍历所有的目录)
结构
存储结构
磁盘:物理意义上的磁盘
分区:逻辑意义上的磁盘:多个磁盘可以合并成一个分区进行管理 & 一个磁盘可以采用多个分区进行管理
卷:实现了文件系统的分区:每个卷都可以采用不同的文件管理系统
注:每个计算机可能有多个不同的文件管理系统
目录结构
单级目录:
- 定义:所有文件都通过一个目录进行保存
- 细节:所有文件的名称都是不可以相同的
两级目录
定义:(1) 主文件目录 用于区分不同的用户 (2) 每个用户拥有自己的 用户文件目录
细节:
(2) 不同用户的用户文件目录的条目名可以相同 & 同一个用户的用户文件目录中的条目名也不可以重复
(3) 用户无法对自己拥有的文件继续分类 & 部分系统限制用户之间不可以访问彼此的用户文件目录
树形目录
定义:(1) 每个目录包含文件和子目录 (2)采用 ==路径名== 的形式来访问文件而不是根据用户来访问文件
路径名
- 绝对路径:从文件所在的根目录开始到当前文件所在的位置:
D:\Typora\Typora\File\JVM.assets
- 相对路径:从进程所在的目录开始到当前文件所在的位置:
File\JVM.assets
- 绝对路径:从文件所在的根目录开始到当前文件所在的位置:
目录删除:(1) 直接删除该目录下的所有文件和子目录 (2) 需要优先删除该目录拥有的文件和子目录才可以删除该目录
注:两者区别在于前者允许删除不为空的目录,后者禁止删除不为空的目录
细节:
(1) 不同的用户可以访问彼此创建的文件
无环图目录
定义:在树形目录的基础上允许不同的目录 共享 相同的文件或者子目录
实现方式:
链接方式:(1) 创建 链接条目 (2) 链接条目是指向共享文件的指针 (3) 相当于目录中并不包含真实的文件而是文件指针
注:遍历目录时会忽略这些链接进行遍历 (避免重复遍历同一文件)
复制:(1) 复制多份共享文件 (2) 每个需要共享该文件的目录都拥有该副本
删除问题:(复制方式在删除时显然只需要将副本一起删除就行,链接方式则涉及到链接的保留问题)
- 软链接:允许原始文件被删除后仍保留当前的链接条目 (试图访问指向为空的链接条目被认为是非法的)
- 硬链接:不允许直接删除原始文件而是在删除所有的链接条目都被删除后才可以删除 (显然需要使用计数的变量来确定当前的链接条目数)
挂载
定义:操作系统使存储设备中的文件和目录可以通过文件系统访问的过程
过程:
- 存储设备被挂载到目录 (文件系统) 下后 -> 该目录就会拥有该存储设备中的数据
- 存储设备被卸载后 -> 目录中的数据会排队写入磁盘中
细节:
- 存储设备被使用之前都必须进行挂载 & 计算机关机后存储设备也会进行卸载
- 挂接的位置叫做挂载点
共享
多用户共享:采用 ==用户和组== 的概念
用户(所有者):
- 定义:分为超级用户、普通用户、虚拟用户 (注:这里是按照
Linux
进行划分的) - 超级用户:具有 更改其余用户的访问权限 和 修改文件的权限 -> 具有最高的权限
- 普通用户:仅能够使用超级用户 授予的权限
- 定义:分为超级用户、普通用户、虚拟用户 (注:这里是按照
组:具有相同权限的用户的集合
细节:
- 用户和组的 ID 将会和文件的属性一起存储在文件控制块中
Windows 7
和Windows 10
开始支持多用户多任务 &Windows XP
不支持多用户多任务 &Linux
天生支持多用户
多文件系统共享:(1) 分布式系统 (2)
FTP
文件传输 (3)WWW
万维网
文件系统实现
概述
- 卷引导控制块:
- 定义:存放引导并加载操作系统的信息 ( BIOS(加载程序) 使用引导控制块加载操作系统 )
- 细节:(1) 没有存放操作系统的磁盘引导控制块的信息为空 (2)
UFS
称为 引导块 &NTFS
称为 分区引导扇区
- 卷控制块
- 定义:存放每个分区的详细信息 (块数量,块大小,空闲
FCB
和 空闲块) - 细节:
UFS
称为 超级块 &NTFS
仍然称为卷控制块并且存放在 主控文件表 中
- 定义:存放每个分区的详细信息 (块数量,块大小,空闲
- 目录结构 & 文件控制块
- 定义:每个目录结构中都存放文件控制块的指针 -> 文件控制块实际存放在磁盘中的某个位置
- 细节:
NTFS
中将 目录结构 同样存放在 主控文件表 中并且 文件控制块 的存放采用 关系型数据库 的方式
- 挂载表:
- 定义:存放当前被挂载到文件系统上的磁盘的信息
- 细节:挂载表在计算机启动之后就会被加载到内存中
- 打开文件表:(1) 系统打开文件表 (2) 进程打开文件表
实现结构
逻辑文件系统
过程:逻辑文件系统管理文件目录 -> 文件目录中的每个条目都是元数据信息 -> 每个元数据信息实际就是
FCB
文件组织模块:
- 功能:(1) ==将逻辑块号映射成物理块号== (2) 管理磁盘中块的分配情况
- 过程:修改逻辑文件系统传递高级指令,将逻辑块号修改成物理块号
基本文件系统:(1) 接收文件组织模块传递的指令并交付给 I/O 控制层 (2) 负责
DMA
机制的缓冲区管理:磁盘向内存中传输数据之前先开辟内存缓冲区 (3) 缓存常用的文件系统的元数据I/O 控制层
组成:==设备驱动程序 + 中断控制程序 + 设备控制器==
功能:接收高层指令操控具体 I/O 设备
过程:
(1) 设备驱动程序 接收 基本文件系统 传递的 高级命令 并将其转换为 机器指令
(2) 设备驱动程序将机器指令交付给 设备控制器
(3) 设备控制器根据机器指令操控具体的 I/O 设备
细节:
- 文件系统分层会增大操作系统的开销降低操作系统的性能
- I/O 控制层 和 基本文件系统 的代码可以复用在不同的文件系统 & 不同的文件系统拥有不同的 逻辑文件系统 和 文件组织模块
UNIX
使用UFS
(UNIX File System
) &Windows
使用NTFS
(Windows NT File System
) &Linux
使用ext
(Extended File System
)- 现代操作系统基本都支持多种文件系统 (思考:多个文件系统要怎么实现呢?提供给用户的接口应该是统一的,那么目录结构也应该统一才对)
虚拟文件系统
实现操作
创建文件
- 逻辑文件系统为新文件分配一个空闲的
FCB
并初始化FCB
- 逻辑文件系统向低层的机构发出指令将磁盘中的 目录结构加载到内存中
- 逻辑文件系统将新的
FCB
更新到目录结构中再写回到磁盘中
- 逻辑文件系统为新文件分配一个空闲的
打开文件
确定当前文件是否已经被打开
(1) 如果当前文件没有被打开 -> 将该文件的
FCB
复制到系统打开文件表中 -> 在该 进程打开文件表 中 创建条目 并指向 系统打开文件表 中的该文件(2) 如果当前文件已经被打开 -> 在该 进程打开文件表 中 创建条目 并指向 系统打开文件表 中的该文件
读文件
写文件
实现目录
- 线性列表
- 实现:目录条目 = ==文件名称 + FCB 指针==
- 优点 & 缺点:
- 优点:实现简单
- 缺点:查找文件是 ==线性搜索==,效率非常低
- 优化方式:(1) 形成有序列表使用二叉搜索 (2) 使用平衡树 (3) 使用缓存
- 重用目录:(1) 将目录条目的名称改为空白 (2) 增加比特位标识使用情况或者表结构记录当前空闲条目 (3) 将目录结构最后一条复制到暂时不使用的位置并且清除最后一条
- 哈希列表
- 实现:(1) 基于线性列表实现 (2) 构建哈希表:每个文件名称都对应一个哈希值 & 线性列表中的文件名称被更换成哈希值
- 优点 & 缺点
- 优点:搜索加速 (哈希表代替了线性搜索 -> 本质就是缓存)
- 缺点:(1) 哈希表大小受限 (2) 可能出现哈希冲突
实现分配
前提:
- 操作系统仅对同一文件系统采用一种分配方法
- 操作系统的视角:磁盘空间由复数个块组成 -> 最小的存储单元是块
- 磁盘的视角:最小的存储单元是扇区 -> 每个块包含多个扇区
连续分配
定义:每个文件在磁盘空间中占有一组连续的物理块
优点:
(1) 寻道时间最短 & 寻道数量最少:所有的块(扇区)几乎都分布的磁道的数量不多,磁头寻道的时间就少
(2) 支持顺序访问和直接访问
缺点:
(1) 难以确定文件实际大小:空间如果分配过大会导致 内部碎片 & 空间如果分配过小会导致文件后续难以扩展
(2) 可能产生外部碎片:每个块可能存放的是不同文件的数据 -> 导致产生无法存放任何数据的孔
解决方式:
(1) 重新启动程序并且重新分配空间 (2) 开辟更大的空间并且将当前的空间内容复制过去 (缺点:非常耗时)
扩展文件系统:开辟新的空间作为文件的扩展空间使用 & 并且记录扩展空间的地址、块数
非连续分配
链接分配
定义:(1) 每个文件在磁盘空间中占有的物理块是分散的 (2) 每个物理块都具有下一个物理块的块号 (指针)
优点:(1) 不会产生外部碎片 (每个块都是专属于一个文件的) (2) 不会产生文件扩展问题:(文件扩展时只需要链接空闲块就行)
缺点:
(1) 仅支持顺序访问 解决方式:文件分配表
(2) 每个块存放数据 + 指针两种信息 导致文件实际占用的空间大于文件本身的大小
解决方式:采用 簇 为磁盘最小存储单位,每个簇包含多个块,每个簇使用一个指针
(3) 不具有可靠性:指针出现损坏或者错误就会导致文件数据丢失
解决方式:(1) 采用双向链表 (即使出现指针错误也能勉强找到文件的块) (2) 每块存储文件名称和逻辑块号 (即使指针错误也可以利用这两个参数找到) (3) 文件分配表
文件分配表:
定义:(1) 每个磁盘块都对应一个条目 & 使用 块号索引条目 (2) 每个条目包含下一个物理块的块号 (指针)
注:只需要通过物理块就可以找到对应的数据了也就是说物理块号就是磁盘地址
优点:(1) 改善随机访问的时间 (2) 指针的的损坏不会导致数据丢失
缺点:(1) 过大的文件会导致
FAT
很大 (2)FAT
可能导致大量的寻道时间
索引分配
- 定义:(1) 每个文件拥有 ==索引块== (包含所有物理块的块号) (2) 系统通过索引块获取索引进而获取物理块
- 优点:(1) 支持直接访问和顺序访问 (2) 不会产生外部碎片问题
- 缺点:索引需要的空间很大
实现空间管理
- 位向量
- 链表
- 组
- 计数