十二、文件系统

文件系统

基本概念
文件系统和文件

文件系统是操作系统中管理持久性数据的子系统,提供数据存储和访问功能。(一种用于持久性存储的系统抽象)

  • 在存储器上组织、检索、读写访问数据

  • 大多数计算机系统都有文件系统

  • 个人电脑、服务器、笔记本电脑

  • iPod、机顶盒、手机
  • Google也是一个文件系统

文件是具有符号名,由字节序列构成的数据项集合。(文件是文件系统中一个单元的相关数据在操作系统中的抽象)

  • 文件系统的基本数据单位

  • 文件名是文件的标识符号

文件系统的功能

分配文件磁盘空间

  • 管理文件块位置和顺序)

  • 管理空闲空间(位置)

  • 分配算法 (策略)

管理文件集合

  • 定位文件及其内容
  • 命名:通过名字找到文件

  • 最常见:分层文件系统

  • 文件系统结构:文件组织方式

数据可靠和安全

  • 安全:分层来保护数据安全
  • 可靠性/持久性:保护文件的持久即使发生崩溃、媒体错误、攻击等
文件属性

文件属性

  • 名称、类型、位置、大小、保护、创建者、创建时间、最近修改时间(这些元数据保存在文件头中或者文件块中)

文件头

  • 在存储元数据中保存了每个文件的信息
  • 保存了文件的属性
  • 跟踪哪一块存储块属于逻辑上文件结构的哪个偏移
文件描述符

文件访问模式

  • 进程访问文件数据前必须先“打开”文件

    f = open(name, flag);

    read(f, …);

    close(f);
  • 内核跟踪进程打开的所有文件

    操作系统为每个进程维护一个打开文件表

    一个打开文件描述符(f)是这个表中的索引

需要元数据数据来管理打开的文件(操作系统在打开文件表中维护打开文件状态和信息

  • 文件指针:最近一次读写位置,每个进程分别维护自己的打开文件指针

  • 文件打开计数:当前打开文件的次数,最后一个进程关闭文件时,将其从打开文件表中移除

  • 文件的磁盘位置:缓存数据访问信息
  • 访问权限:每个进程的文件访问模式信息

文件的用户视图和系统视图

文件的用户视图:持久的数据结构

系统访问接口:字节序列的集合(UNIX),系统不关心存储在磁盘上的数据结构

操作系统的文件视图

  • 数据块的集合(数据块是逻辑存储单元,而扇区是物理存储单元)

  • 块大小<>扇区大小:在Unix中,块的大小是4kB

文件系统中的基本操作单位是数据块:例如, getc()putc()即使每次只访问1字节的数据,也需要缓存目标数据4096字节


用户看到是抽象的一维的线性数据空间,系统看到磁盘块

访问模式

操作系统需要了解进程如何访问文件

顺序访问: 按字节依次读取,大多数的文件访问都是顺序访问

随机访问: 从中间读写,不常用, 但仍然重要,例如, 虚拟内存中把内存页存储在文件

索引访问: 依据数据特征索引,通常操作系统不完整提供索引访问,相反,数据库是建立在索引内容的磁盘访问上(需要高效的随机访问)


文件内部结构(应用系统打开复杂文件,但对操作系统该文件可能很简单,就是字节流 )

  • 无结构:单词,字节序列
  • 简单记录结构:列,固定/可变长度 
  • 复杂结构:格式化文档(MS Word, PDF),可执行文件

文件共享和访问控制

  • 多用户系统中的文件共享是很必要的
  • 访问控制

    每个用户能够获得哪些文件的哪些访问权限

    访问模式: 读、写、执行、删除、列表等

  • 文件访问控制列表(ACL):<文件实体, 权限>
  • Unix模式

      <用户||所有人, ||可执行>

       用户标识ID:识别用户, 表明每个用户所允许的权限及保护模式

       组标识ID:允许用户组成组,并指定了组访问权限

语义一致性

  • 规定多进程如何同时访问共享文件

    与同步算法相似

    因磁盘I/O和网络延迟而设计简单

  • Unix 文件系统(UFS)语义

       对打开文件的写入内容立即对其他打开同一文件的其他用户可见

       共享文件指针允许多用户同时读取和写入文件

会话语义:写入内容只有当文件关闭时可见

读写锁:一些操作系统和文件系统提供该功能

目录

分层文件系统

  • 文件以目录的方式组织起来

  • 目录是一类特殊的文件:目录的内容是文件索引表<文件名, 指向文件的指针>

  • 目录和文件的树型结构:

    早期的文件系统是扁平的 (只有一层目录)


目录操作

  • 典型目录操作:搜索文件,创建文件,删除文件,枚举目录,重命名文件,在文件系统中遍历一个路径 
  • 操作系统应该只允许内核修改目录:确保映射的完整性,应用程序通过系统调用访问目录(如ls)

目录实现

  • 文件名的线性列表,包涵了指向数据块的指针,编程简单,执行耗时

  • 哈希表– 哈希数据结构的线性表

    减少目录搜索时间

    碰撞– 两个文件名的哈希值相同

    固定大小

名字解析路径遍历)

  • 名字解析: 把逻辑名字转换成物理资源(如文件)

    依据路径名,在文件系统中找到实际文件位置

    遍历文件目录直到找到目标文件

  • 举例: 解析“/bin/ls

    读取根目录的文件头 (在磁盘固定位置)

    取根目录的数据块搜索“bin”

    读取bin的文件头

    读取bin的数据块; 搜索ls

    读取ls的文件头

  • 当前工作目录 (PWD)

      每个进程都会指向一个文件目录用于解析文件名

      允许用户指定相对路径来代替绝对路径,如,用PWD=“/bin” 能够解析ls

文件系统挂载

  • 文件系统需要先挂载才能被访问

  • 一个未挂载的文件系统被挂载在挂载点上

文件别名

  • 两个或多个文件名关联同一个文件

  • 硬链接: 多个文件项指向一个文件

  • 软链接: 以“快捷方式”指向其他文件,通过存储真实文件的逻辑名称来实现(文件的内容为另一个文件的路径名

如果删除了一个有别名的文件会如何呢?

  • 如果是软链接,这个别名会成为一个空指针 
  • 如果是硬链接,可能有一个隐形计数器,删除一次减一,直到为0时才真正删除

backpointers 反向指针 方案 

  • 每个文件有一个包含多个backpointer的列表,所以删除所有的backpointer
  • backpointer使用菊花链管理

添加间接层,即目录项数据结构(先指向间接层,再指向真实的文件)

  • 链接:已存在文件的另一个名字(指针)
  • 链接处理:根据指针来定位文件

文件目录中的循环

如何保证没有循环?

  • 只允许到文件的链接,不允许在子目录的链接

  • 增加链接时,用循环检测算法确定是否合理

更多实践——限制路径可遍历文件目录的数量

文件系统的类别

磁盘文件系统

  • 文件存储在数据存储设备上, 如磁盘
  • 例如:FAT(早起windows), NTFS(现在windows), ext2/3(unix,linux), ISO9660(光盘)

数据库文件系统

  • 文件特征是可被寻址(辨识)的

  • 例如: WinFS

日志文件系统

  • 记录文件系统的修改/事件(读写操作要么完成,要么不做,避免打断)

  • 例如:journaling file system

网络/分布式文件系统

  • 例如: NFS(网络), SMB(网络), AFS(分布式), GFS(google文件系统,分布式)

特殊/虚拟文件系统:以文件的方式展现读写的接口,来交互访问内核中的数据

网络/分布式文件系统

文件可以通过网络被共享

  • 文件位于远程服务器

  • 客户端远程挂载服务器文件系统

  • 标准系统文件访问被转换成远程访问

  • 标准文件共享协议:NFS for Unix, CIFS for Windows

分布式文件系统的挑战

  • 客户端和客户端上的用户辨别起来很复杂,例如, NFS是不安全的

  • 一致性问题

  • 错误处理模式

虚拟文件系统

分层结构

  • 上层:虚拟(逻辑)文件系统
  • 底层:特定文件系统模块

目的:对所有不同文件系统的抽象

功能: 

提供相同的文件和文件系统接口 ,管理所有文件和文件系统关联的数据结构, 高效查询例程,遍历文件系统 ,与特定文件系统模块的交互

虚拟文件系统存在于内存中,当OS创建后会创建虚拟文件子系统

基本数据结构:

  • 卷控制块(Unix:superblock ):每个文件系统一个,包括文件系统详细信息,包括块,块大小,空余块,计数/指针等 
  • 文件控制块(Unix:VNODE/INODE): 每个文件一个,文件的详细信息 ,包括许可、拥有者、大小、数据库位置等
  • 目录节点(linux:dentry):每个目录项一个;将目录项数据结构及树性布局编码成树型数据结构;指向文件控制块、父节点、项目列表等

卷控制块(每个文件系统一个)、文件控制块(每个文件一个)、目录节点(每个目录项一个)都会映射到磁盘系统的一个或者对个扇区

持续存储在二级存储中:分配在存储设备的数据块中

当需要时加载进内存

  • 卷控制块:当文件系统挂载时进入内存
  • 文件控制块:当文件被访问时进入内存
  • 目录节点: 在遍历一个文件路径时进入内存

数据缓存

虽然内存容量比内存大,但是硬盘数据访问太慢,为了能够提高速度,在内存仿一块缓存,把经常用到的或者当前正在访问的数据从硬盘读到内存中,接下来访问在内存中进行,提高效率


数据块缓存

数据块按需读入内存

  • 提供read()操作

  • 预读: 预先读取后面的数据块

数据块使用后被缓存

  • 假设数据将会再次用到

  • 写操作可能被缓存和延迟写入

两种数据块缓存方式(怎么样组织)

  • 普通数据块缓存

  • 页缓存: 统一缓存数据块和内存页


页缓存

  • 分页要求:当需要一个页才将其载入内存
  • 虚拟页式存储:在虚拟地址空间中虚拟页面可映射到本地文件中(在二级存储中)


  • 文件数据块的页缓存

    在虚拟内存中文件数据块被映射成页

    文件的读/写操作被转换成对内存的访问

    可能导致缺页和/或设置为脏页

    问题: 页置换算法需要协调虚拟存储和页缓存间的页面数


打开文件的数据结构

打开文件首先要在硬盘中找到文件的位置,所谓开开就是将硬盘中关于文件控制块的内容读到内存中,将相关信息放到打开文件表中,文件表中设置一个项,将项的索引fd返回给应用程序(fd=fopen()),应用程序就可以基于索引进行读写。

文件描述符

  • 每个被打开的文件都有一个文件描述符

  • 文件状态信息:目录项、当前文件指针、文件操作设置等

打开文件表

  • 一个进程一个
  • 一个系统级的的打开文件表
  • 如果有文件被打开的将不能卸载

 

打开文件锁:一些文件系统提供文件锁,用于协调多进程的文件访问

  • 强制–根据锁保持情况和访问需求确定是否拒绝访问

  • 劝告 – 进程可以查找锁的状态来决定怎么做

文件分配

打开文件之后可能要进行写操作,就要设计到对文件空间的管理。

文件大小

大多数文件都很小

  • 需要对小文件提供很好的支持

  • 块空间不能太大

一些文件非常大

  • 必须支持大文件 (64位文件偏移)

  • 大文件访问需要高效

文件分配

如何给一个文件分配数据块

分配方式

  • 连续分配
  • 链式分配
  • 索引分配

指标

  • 存储效率外部碎片等

  • 读写性能:访问速度

连续分配

  • 文件头指定起始块和长度
  • 分配策略:最先匹配, 最佳匹配, ...(内存分配的方法)

  • 优点:文件读取表现好,高效的顺序和随机访问 

  • 缺点:碎片,文件增长问题(预分配?,按需分配?)


链式分配

  • 文件以数据块链表方式存储

  • 文件头包含了到第一块和最后一块的指针

  • 优点:创建、增大和缩小容易,没有碎片 

  • 缺点:不可能真正地随机访问,可靠性(破坏一个链然后整个文件都丢失了)

索引分配

  • 为每个文件创建一个名为索引数据块的非数据数据块——指向文件数据块的指针列表
  • 文件头包含了索引数据块指针

  • 优点:创建,增大缩小都很容易,没有碎片,支持直接访问 

  • 缺点:当文件很小时,存储索引的开销,如何处理大文件?大文件的索引块要很大,如何组织索引? 

大文件的索引分配

早期的Unix是多级索引方式(UFS多级索引分配)


文件头包含13个指针:10 个指针指向数据块,11个指针指向索引,12个指针指向二级索引块,13个指针指向三级索引块

效果:提高了文件大小限制阀值,动态分配数据块,文件扩展很容易,小文件开销小,只为大文件分配间接数据块,大文件在访问数据块时需要大量查询。

空闲空间列表

跟踪记录文件卷中未分配的数据块,空闲空间列表存储在哪里?采用什么数据结构表示空闲空间列表?

空闲空间组织: 位图

  • 用位图代表空闲数据块列表

    111111111111111001110101011101111...

    i = 0 表明数据块i是空闲, 否则,表示已分配

  • 使用简单但是可能会是一个大的很大向量表

    160GB磁盘-> 40M数据块-> 5MB位图

    假定空闲空间在磁盘中均匀分布,则找到“0”之前要扫描n/r ,n = 磁盘上数据块的总数,r = 空闲块的数目


其他空闲空间组织方式


多磁盘管理——RAID

磁盘分区

通常磁盘通过分区来最大限度减小寻道时间

  • 一个分区是一组柱面的集合

  • 每个分区都可视为逻辑上独立的磁盘

磁头的前后寻道(最慢),磁盘在旋转。

分区:硬件磁盘的一种适合操作系统指定格式的规划

卷:一个拥有一个文件系统实例的可访问的存储空间,通常常驻在磁盘的单个分区上。(一个文件系统由分区组成,一个磁盘可以有多个分区,一个卷拥有多个分区,可以把文件系统扩展到多个磁盘上)


多磁盘管理

使用多磁盘可改善:吞吐量(通过并行),可靠性和可用性 (通过冗余)

冗余磁盘阵列(RAID, Redundant Array of InexpensiveDisks)

  • 多种磁盘管理技术

  • RAID分类,,RAID-0, RAID-1, RAID-5

实现:

  • 软件:操作系统内核的文件卷管理(在文件系统之下,在磁盘驱动之上有个RAID层,完成磁盘阵列管理)

  • 硬件:RAID硬件控制器(I/O)(RAID硬件控制器映射出一个虚拟硬盘)

RAID-0:磁盘条带化

把数据块分成多个子块,存储在独立的磁盘中,通过独立磁盘上并行数据块访问提供更大的磁盘带宽

RAID-1: 磁盘镜像

向两个磁盘写入,从任何一个读取,可靠性成倍增长,读取性能线性增加


RAID-4: 带校验的磁盘条带化

数据块级的磁盘条带化加专用奇偶校验磁盘,允许从任意一个故障磁盘中恢复

出现一个故障可以恢复,校验磁盘是其他盘的奇偶校验。忘其他盘写数据时,也要往校验磁盘写,开销很大。

RAID-5: 带分布式校验的磁盘条带化


带化和奇偶校验按“字节”或者“

  • RAID-0/4/5: 基于数据块

  • RAID-3: 基于位

RAID-5: 每组条带块有一个奇偶校验块,允许一个磁盘错误

RAID-6: 组条带块有两个冗余块,允许两个磁盘错误



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值