loading...

24文件系统

4.1 文件基本概念

文件:

  • 一组具有意义的信息/数据集合

文件属性

创建时间、上次修改时间文件所有者信息

文件名:

  • 由创建文件的用户决定文件名,主要是为了方便用户找到文件
  • 同一目录下不允许有重名文件

标识符:

  • 一个系统内的各文件标识符唯一
  • 标识符对用户来说毫无可读性,它只是操作系统用于区分各个文件的一种内部名称

类型:

  • 指明文件的类型
  • 类型名告知操作系统,用户在打开该文件时所使用的默认软件

位置:

  • 文件存放的路径(让用户使用)、在外存中的地址(操作系统使用,对用户不可见)
  • 当用户对文件进行打开操作时,操作系统需要将外存中的文件数据读入内存

大小:

  • 指明文件大小

保护信息:

  • 对文件进行保护的访问控制信息

4.1.1 文件的组织与管理

数据项是文件系统中最基本的数据单位

文件分为以下两种主要逻辑结构:

  • 无结构文件:
    • 由一些二进制或字符流组成,又称"流式文件"
    • 如文本文件
  • 有结构文件:
    • 由一组相似的记录组成,又称"记录式文件"
      • 记录是一组相关数据项的集合
    • 如数据库表

系统中的各个文件通过一层一层的目录合理有序的组织起来

  • 目录:
    • 即"文件夹",其实也是一种特殊的有结构文件(由记录组成)
  • 用户可以自己创建一层一层的目录,各层目录中存放相应的文件

操作系统提供给文件的基本系统调用功能:

  • 创建文件:
    • 用户点击新建后,图形化交互进程在背后create系统调用
  • 删除文件:
    • 用户点击删除后,图形化交互进程通过delete系统调用,将文件数据存外村中删除
  • 读文件:
    • 用户双击,记事本等应用程序通过read系统调用,将文件从外存读入内存,并显示在屏幕中
    • 文件数据存储在外村中,只有将文件数据读入内存后才能让CPu处理
  • 写文件:
    • 用户通过记事本等应用程序,编辑文件中的内容,点击保存后,记事本等应用程序通过write系统调用,将文件数据从内存写回外存
    • 如果不进行保存,修改的内容一直存放在内存中,不会更新到外存中
  • 打开文件:
    • 用户启动记事本等应用程序后,记事本会执行open系统调用,打开对外村数据的访问通道
  • 关闭文件:
    • 用户关闭记事本等应用程序后,记事本退出前会执行close系统调用,关闭对外存数据的访问通道

可用几个基本操作完成更复杂的操作,比如:"复制文件":先创建一个新的空文件,再把源文件读入内存,再将内存中的数据写到新文件中

文件在外存的存放方式:

  • 与内存一样,外存也是由一个个存储单元组成的
    • 每个存储单元可以存储一定量的数据(如1B)
    • 每个存储单元对应一个物理地址
  • 类似于内存分为一个个"内存块",外存会分为一个个"块/磁盘块/物理块"
    • 每个磁盘块的大小是相等的,每块一般包含2的整数幂个地址(如一块包含2\(^{10}\)个地址,即1KB)
    • 同样类似的是,文件的逻辑地址也可以分为(逻辑块号,块内地址),操作系统同样需要将逻辑地址转换为外存的物理地址(物理块号,块内地址)的形式
    • 块内地址的位数取决于磁盘块的大小
  • 操作系统以"块"为单位为文件分配存储空间,因此即使一个文件大小只有10B,但它依然需要占用1KB 的磁盘块
    • 外存中的数据读入内存时同样以块为单位,即内存与外存的数据交换单位也是块

文件的物理结构:

  • 文件数据可以存放在连续的磁盘块中,也可以离散的存放在几个磁盘块

其他操作系统实现的文件管理功能:

  • 文件共享:使多个用户可以共享使用一个文件
  • 文件保护:如何保证不同的用户对文件有不同的操作权限

4.2 文件的逻辑结构

文件逻辑结构:

  • 在用户看来,文件内部的数据应该是如何组织起来的
    文件物理结构:
  • 在操作系统看来,文件的数据是如何存放在外存中的

类比数据结构的逻辑结构和物理结构,文件操作的具体实现与逻辑结构、物理结构都有关

4.2.1 无结构文件:

  • 文件内部的数据就是一系列二进制流或字符流组成,又称"流式文件"
  • 如:Windows 操作系统中的.txt 文件

文件内部的数据其实就是一系列字符流,没有明显的结构特性,因此也不用探讨无结构文件的"逻辑结构"问题

4.2.2 有结构文件:

由一组相似的记录组成,又称"记录式文件"。每条记录又若干个数据项组成

  • 一般来说,每条记录有一个数据项可作为关键字(作为识别不同记录的ID)

根据各条记录的长度(占用的存储空间)是否相等,可分为以下两类:

  • 定长记录:
    • 每条记录的长度均相同,各数据项都处于记录中的相同位置,具有相同的顺寻和长度
  • 可变长记录:
    • 由于数据项的长度不确定,导致每条记录的长度也不确定,甚至有些数据项在某些记录中不存在

根据有结构文件中的各条记录在逻辑上如何组织,可以分为以下三类:
顺序文件:

  • 文件件中的记录一个接一个地顺序排列(逻辑上),记录可以是定长的或可变长的。各个记录在物理上可以顺序存储或链式存储
  • 顺序存储:
    • 逻辑上相邻的记录,物理上也相邻(类似顺序表)
  • 链式存储:
    • 逻辑上相邻的记录物理上不一定相邻(类似于链表)
  • 按照记录的顺序是否与关键词相关,可分为:
    • 串结构:记录顺序与关键词无关
      • 通常按照记录存入的时间决定记录的顺序,但时间不一定作为主键
    • 顺序结构:记录按照关键词顺序排序

关于顺序结构是否能够进行随机存取

逻辑结构 是否可随机存取
链式存储 不论是定长/克定昌记录,都无法实现随机存取
每次只能从第一个记录开始依次往后查找
顺序可变长记录存储 无法实现随机存取,每次只能从第一个记录开始依次往后查找
顺序定长记录存储 可实现随机存取,假设记录长度为L,则第i个记录存放的相对位置是i*L
1)若采用传结构,则无法快速找到某关键字对应的记录
2)若采用顺序结构,可以快速找到某关键字对应的记录(如折半查找)
  • 显然,只有定长记录的顺序文件可以实现随机存取
  • 一般考试题目中提到的顺序文件指的是物理上顺序存储的顺序文件
  • 顺序文件的缺点便是增加/删除一个记录比较困难(串结构不考虑记录内关键词的顺序,直接增加/删除相对容易些)

操作系统一般会将在主存中的增删改操作保存在专门的日志中,每隔一定时间将这些日志操作的最终结果同步到外存中,以此减少I/O次数

索引文件:

  • 在顺序文件基础上,建立一张索引表以加快文件检索速度,每条记录对应一个索引项
    • 索引表本身是定长记录的顺序文件,因此可以快速找到第i 个记录对应的索引项
    • 可将关键字作为索引号内容,若按关键字顺序排列,则还可以支持按照关键字折半查找
    • 每当增加/删除一个记录时,需要对索引表进行修改
  • 由于索引文件有很快的检索速度,主要用于对信息处理的及时性要求比较高的场合
  • 可用不同的数据项建立多个索引表
    • 如:学生信息表中,可用关键字"学号"建立一张索引表。也可用"姓名"建立一张索引表。这样就可以根据"姓名"快速地检索文件了
    • SQL 就支持根据某个数据项建立索引的功能

索引顺序文件:

  • 索引顺序文件是索引文件和顺序文件思想的结合。索引顺序文件中,同样会为文件建立一张索引表
    • 但该索引表并不是每个记录对应一个索引表项,而是一组记录对应一个索引表项
  • 索引顺序文件的索引项也不需要按关键字顺序排列,这样可以极大地方便新表项的插入

假设一个非定长、顺序结构的顺序文件有10000个记录

  • 采用关键字检索
    • 只能顺序查找,平均查找5000次
  • 采用索引顺序文件结构:
    • 可将10000个记录分为100组,每组100个记录
    • 顺序查找索引表找到分组,平均查找50个组
    • 在找到的分组顺序查找记录,平均查找50个记录
    • 采用索引顺序结构,平均共计查找100次
  • 建立一个索引表相比关键字检索可以减少大量的查找次数,但是对于数量较多的记录,单级索引顺序表,查找次数依旧较多

为了进一步提高检索效率,可以为顺序文件建立多级索引表

  • 要为N 个记录的文件建立K 级索引,则最优的分组是每组N\(^{1/(K+1)}\) 个记录
  • 检索一个记录的平均查找次数是$\frac{N^{1/(K+1)}}{2} * $(K+1)

4.3 文件目录

使用文件目录结构,可以让文件之间的组织结构清晰,易于用户查找

  • 编程时也可以很方便的用文件路径找到一个文件
  • 如:FILE *fp;fp=fopen("F:\data\myfile.dat");用户可以轻松实现"按名存取"
  • 目录本身就是一种有结构文件,由一条条记录组成。每条记录对应一个在该放在该目录下的文件
  • 目录文件中的一条记录就是一个"文件控制块(FCB)"

文件控制块FCB:

  • FCB 的有序集合称为"文件目录",一个FCB就是一个文件目录项
  • FCB 中包含了文件的基本信息(文件名、物理地址、逻辑结构、物理结构等),存取控制信息(是否可读/可写、禁止访问的用户名单等),使用信息(如文件的建立时间、修改时间等)
    • 最重要,最基本的文件信息还是文件名、文件存放的物理地址
  • FCB 实现了文件名和文件之间的映射,使用户(用户程序)可以实现"按名存取"

对目录可进行的操作包括以下几类:

  • 搜索:
    • 当用户要使用一个文件时,系统要根据文件名搜索目录,找到该文件对应的目录项
  • 创建文件:
    • 创建一个新文件时,需要在其所属的目录中增加一个目录项
  • 删除文件:
    • 当删除一个文件时,需要在目录中删除相应的目录项
  • 显示目录:
    • 用户可以请求显示目录的内容,如显示该目录中的所有文件及相应属性
  • 修改目录:
    • 某些文件属性保存在目录中,因此这些属性变化时需要修改相应的目录项(如:文件重命名)

目录结构分为以下几类:

  • 单级目录结构:

    • 早期操作系统并不支持多级目录,整个系统中只建立一张目录表,每个文件占一个目录项(整个系统只有一张目录表)
    • 单级目录实现了"按名存取",但是不允许文件重名
    • 在创建一个文件时,需要先检查目录表中有没有重名文件,确定不重名后才能允许建立文件,并将新文件对应的目录项插入目录表中
    • 单级目录结构不适用于多用户操作系统
  • 两级目录结构:

    • 早期的多用户操作系统,采用两级目录结构。分为主文件目MFD,Master File Directory和用户文件目录UFD,User Flie Directory
    • 主文件目录:记录用户名及相应用户文件目录的存放位置
    • 用户文件目录:
      • 由该用户的文件FCB组成
      • 用户文件目录允许不同用户的文件重名。文件名虽然相同,但是对应的其实是不同的文件
    • 两级目录结构允许不同用户的文件重名,也可以在目录上实现实现访问限制(检查此时登录的用户名是否匹配)
    • 两级目录结构依然缺乏灵活性,用户不能对自己的文件进行分类
  • 多级目录结构:(树形目录结构)

    • 用户(或用户进程)要访问某个文件时要用文件路径名标识文件,文件路径名是个字符串。各级目录之间用"/"隔开。从根目录出发的路径称为绝对路径
    • 例如,自拍.jpg 的绝对路径是 "/照片/2015-08/自拍.jpg"
      • 系统根据绝对路径一层一层地找到下一级目录。刚开始从外存读入根目录的目录表
      • 找到"照片"目录的存放位置后,从外存读入对应的目录表
      • 再找到"2015-08"目录的存放位置,再从外存读入对应目录表
      • 最后才找到文件"自拍.jpg"的存放位置
      • 整个过程需要3次读磁盘I/O操作
    • 假如每次都从根目录开始查找,是很低效的。因此可以设置一个"当前目录"
      • 例如,此时已经打开了"照片"的目录文件,也就是说,这张目录表已调入内存,那么可以把它设置为"当前目录"。当用户想要访问某个文件时,可以使用从当前目录出发的"相对路径"。
      • 在 Linux 中,"."表示当前目录,因此如果"照片"是当前目录,则"自拍.jpg"的相对路径为:"./2015-08/自拍.jpg"
      • 从当前路径出发,只需要查询内存中的"照片"目录表,即可知道"2015-08"目录表的存放位置,从外存调入该目录,即可知道"自拍.jpg"存放的位置了
      • 引入"当前目录"和"相对路径"后,磁盘I/O的次数减少了。这就提升了访问文件的效率
    • 树形目录结构可以很方便地对文件进行分类,层次结构清晰,也能够更有效地进行文件的管理和保护
    • 但是,树形结构不便于实现文件的共享
  • 无环图目录结构:

    • 在树形目录结构的基础上,增加一些指向同一节点的有向边,使整个目录成为一个有向无环图。可以更方便地实现多个用户间的文件共享
    • 可以用不同的文件名指向同一个文件,甚至可以指向同一个目录(共享同一目录下的所有内容)
    • 需要为每个共享结点设置一个共享计数器,用于记录此时有多少个地方在共享该结点。用户提出删除结点的请求时,只是删除该用户的FCB、并使共享计数器减1,并不会直接删除共享结点
    • 新建文件是,共享计数器初值为1。只有共享计数器减为0时,才删除结点
    • 共享文件不同于复制文件
      • 在共享文件中,由于各用户指向的是同一个文件,因此只要其中一个用户修改了文件数据,那么所有用户都可以看到文件数据的变化

索引节点:对FCB的改进

  • 在查找各级目录的过程中只需要用到"文件名"这个信息,只有文件名匹配时,才需要读出文件的其他信息。因此可以考虑让目录表"瘦身"来提升效率
  • 索引节点包含除了文件名以外的所有信息,每个文件对应一个索引节点,索引表只保留"文件名"以及"索引节点指针"两项数据
    • 假设一个FCB是64B,磁盘块的大小为1KB,则每个盘块中只能存放16个FCB
    • 若一个文件目录中共有640个目录项,则共需要占用 640/16 = 40 个盘块
      • 因此按照某文件名检索该目录,平均需要查询320 个目录项,平均需要启动磁盘20次(每次磁盘I/O读入一块)
    • 若使用索引节点机制,文件名占用14B,索引结点指针占2B,则每个盘块可存放64个目录项
      • 那么按文件名检索目录平均只需要读入 320/64 = 5 个磁盘块,这将大大提升文件检索速度
    • 由于目录项长度减小,每个磁盘块可以存放更多的目录项,检索文件对磁盘的I/O次数减少了很多
  • 当找到文件名对应的目录项时,才需要将索引结点调入内存,索引结点中记录了文件的各种信息,包括文件在外存中的存放位置,根据"存放位置"即可找到文件
  • 存放在外存中的索引结点称为"磁盘索引结点";当索引结点放入内存后称为"内存索引结点"
    • 相比之下内存索引结点中需要增加一些信息
    • 比如:文件是否被修改、此时有几个进程正在访问该文件等

4.4 文件的物理结构

文件的物理结构:

  • 即文件分配方式,表明文件数据存放在外村的方式
  • 磁盘中的存储单元也会被分为一个个"块/磁盘块/物理块"
    • 很多操作系统中,磁盘块的大小与内存块、页面的大小相同
    • 内存与磁盘之间的数据交换(即读/写操作、磁盘I/O)都是以"块"为单位进行的。即每次读入一块,或每次写出一块
  • 在外存管理中,为了方便对文件数据的管理,文件的逻辑地址空间也被分为了一个一个的文件"块"
    • 故文件的逻辑地址也可以表示为(逻辑块号,块内地址)的形式
    • 用户通过逻辑地址来操作自己的文件,操作系统要负责实现从逻辑地址到物理地址的映射

4.4.1 文件分配方式类型

连续分配:

  • 要求每个文件在磁盘上占有一组连续的块
  • 物理块号= 起始块号+ 逻辑块号
  • 优点:
    • 连续分配支持顺序访问和直接访问(即随机访问)
      • 文件目录中记录存放的起始块号和长度(总共占用几个块),可以直接算出逻辑块号对应的物理块号
  • 缺点:
    • 连续分配的文件在顺序读/写时速度最快
      • 读取某个磁盘块时,需要移动磁头
      • 访问的两个磁盘块相隔越远,移动磁头所需时间就越长
    • 物理上采用连续分配的文件不方便拓展
      • 由于文件连续占用磁盘块,如果文件与文件紧挨着放置,当文件大小扩大时,必须要申请更大的连续空间,将原数据复制到新空间,造成读写效率大幅下降
    • 物理上采用连续分配,存储空间利用率低,会产生难以利用的磁盘碎片
      • 由于上面不方便扩展的原因,势必会导致空间较小的空间被空闲出来,造成磁盘碎片

链接分配:

  • 采取离散分配的方式,可以为文件分配离散的磁盘块
  • 隐式链接:
    • 目录中记录了文件存放的起始块号和结束块号
      • 也可以增加一个字段来表示文件的长度
    • 除了文件的最后一个磁盘块之外,每个磁盘块中都会保存指向下一个盘块的指针,这些指针对用户是透明的
    • 优点:
      • 很方便文件拓展,不会有碎片问题,外存利用率高
        • 若此时要拓展文件,则可以随便找一个空闲磁盘块,挂到文件的磁盘块链尾,并修改文件的FCB
    • 缺点:
      • 只支持顺序访问,不支持随机访问,查找效率低
        • 假设访问的逻辑块号i,从FCB中找到起始块号,即0号块,将0号逻辑块读入内存,获得1号块的物理块号,继续将1号块读入内存,找到2好块的物理块号,依次类推
        • 直到读入i号逻辑块,总需要i+1次磁盘I/O
      • 指向下一个盘块的指针也需要额外耗费少量的存储空间

考试题目中遇到未指明隐式/显式的"链接分配",默认指的是隐式链接的链接分配

  • 显式链接:
    • 把用于链接文件各物理块的指针显式地存放在一张表中,即文件分配表FAT,File Allocation Table
      • 故目录中只需记录文件的起始块号
    • 一个磁盘仅设置一张FAT
      • 开机时,将FAT读入内存,并常驻内存
      • FAT 的各个表项在物理上连续存储,且每一个表项长度相同,因此"物理块号"字段可以是隐含的
    • 优点:
      • 很方便文件拓展,不会有碎片问题,外存利用率高,并且支持随机访问
        • 当访问逻辑块号i时,从FCB中找到起始块号,若i为合法编号,则查询主存中文件分配表FAT,往后找到i号逻辑块对应的物理块
        • 检索FAT不需要读磁盘,只需访问主存
      • 相比于隐式链接来说,地址转换时不需要访问磁盘,因此文件的访问效率更高
    • 缺点:
      • 文件分配表FAT的需要占用一定的存储空间

索引分配:

  • 索引分配允许文件离散地分配在各个磁盘块中,系统会为每个文件建立一张索引表,索引表中记录了文件的各个逻辑块对应的物理块
    • 索引表的功能类似于内存管理中的页表,建立逻辑页面到物理页之间的映射关系
    • 索引表存放的磁盘块称为索引块;文件数据存放的磁盘块称为数据块
    • 目录中需要记录文件的索引块是几号磁盘块
  • 假设某个新创建的文件"aaa"的数据依次存放在磁盘块2 -> 5 -> 13 -> 9。7号磁盘块作为"aaa"的索引块,索引块中保存了索引表的内容
    • 在显式链接的链式分配方式中,文件分配表FAT 是一个磁盘对应一张
    • 而索引分配方式中,索引表是一个文件对应一张
  • 优点:
    • 可以支持随机访问
      • 放访问逻辑块号i时,从FCB中找到起始块号,从目录项中得到索引表存放的物理块号,将索引表从外村中读入内存,检索索引表即可对i号块进行直接访问
    • 文件拓展也很容易实现
      • 只需要给文件分配一个空闲块作为索引表,并在索引表增加一个索引表项即可
  • 缺点:
    • 索引表需要占用一定储存空间

若每个磁盘块1KB,一个索引表项4B,则一个磁盘块只能存放256 个索引项,如果一个文件的大小超过了256块,那么一个磁盘块是装不下文件的整张索引表的

可采用以下方案解决上述问题:

  • 链接方案:

    • 如果索引表太大,一个索引块装不下,那么可以将多个索引块链接起来存放
    • 假设磁盘块大小为1KB,一个索引表项占4B,则一个磁盘块只能存放256个索引项
      • 若一个文件大小为256*256KB =65,536 KB = 64MB
      • 该文件共有256*256 个块,也就对应256*256个索引项,也就需要256 个索引块来存储,这些索引块用链接方案连起来
      • 若想要访问文件的最后一个逻辑块,就必须找到最后一个索引块(第256个索引块),而各个索引块之间是用指针链接起来的,因此必须先顺序地读入前255 个索引块
    • 缺点:
      • 若文件很大,索引表很长,就需要将很多个索引块链接起来。想要找到i 号索引块,必须先依次读入0~i-1号索引块,这就导致磁盘I/O次数过多,查找效率低下
  • 多层索引:

    • 建立多层索引(原理类似于多级页表),使第一层索引块指向第二层的索引块
      • 也可根据文件大小的要求再建立第三层、第四层索引块
    • 假设磁盘块大小为1KB,一个索引表项占4B,则一个磁盘块只能存放256 个索引项
      • 若某文件采用两层索引,则该文件的最大长度可以到2562561KB = 65,536 KB = 64MB
      • 根据逻辑块号算出应该在索引表的哪个表项,如访问1026号逻辑块,则1026/256=4,1026%256=2
      • 因此在一级索引表调入内存,查询4号表项(0号为第一个索引表),将其对应的二级索引表调入内存,再查询二级索引表的2号表项可得到1026号逻辑块存放在的磁盘块号
      • 综上所述,访问目标数据块,需要3次磁盘I/O
      • 如果采用三层索引,则文件的最大长度为256256256*1KB=16GB,访问目标数据块,需要4次磁盘I/O
    • 采用k层索引结构,且顶级索引表为调入内存,则访问一个数据块只需要k+1次读磁盘操作
    • 若采用多层索引,则各层索引表大小不饿能超过一个磁盘块
    • 缺点:
      • 即使是小文件,访问一个数据块依然需要K+1次读磁盘
  • 混合索引:

    • 多种索引分配方式的结合
      • 例如,一个文件的顶级索引表中,既包含直接地址索引(直接指向数据块),又包含一级间接索引(指向单层索引表)、还包含两级间接索引(指向两层索引表)
    • 优点:
      • 对于小文件来说,访问一个数据块所需的读磁盘次数更少
        • 0~7号逻辑块采用直接地址,加上索引表的读入需要读两次磁盘;8~263采用一级索引,加上索引表的读入需要读三次磁盘;264~65799采用二级索引,加上索引表的读入需要读四次磁盘
        • 一般计算机中小文件更多,只需要读两次磁盘,因此混合索引可以加快索引速度

索引分配注意点:

  • 计算出文件的最大长度需要结合多层索引、混合索引的结构
    • 各级索引表最大不能超过一个块
  • 计算访问某个数据块所需要的读磁盘次数,注意题目信息
    • FCB中会存有指向顶级索引块的指针,因此可以根据FCB读入顶级索引块
    • 每次读入下一级的索引块都需要一次读磁盘操作
    • 注意题目中,顶级索引块是否已调入内存

各分配方式对比汇总

分配方式 分配描述 目录项内容 优点 缺点
顺序分配 为文件分配的必须是连续的磁盘块 起始块号、文件长度 顺序存取速度快,支持随机访问 会产生碎片,不利于文件拓展
隐式链接 除文件的最后一个盘块之外,每个盘块中都存有指向下一个盘块的指针 起始块号、结束块号 可解决碎片问题,外存利用率高,文件拓展实现方便 只能顺序访问,不能随机访问
显式链接 建立一张文件分配表(FAT),显式记录盘块的先后关系(开机后FAT常驻内存) 起始块号 除了拥有隐式链接的优点之外,还可通过查询内存中的FAT实现随机访问 FAT需要占用一定的存储空间
索引分配 为文件数据块建立索引表。若文件太大,可采用链接方案、多层索引、混合索引 链接方案记录的是第一个索引块的块号,多层/混合索引记录的是顶级索引块的块号 支持随机访问,易于实现文件的拓展 索引表需占用一定的存储空间。访问数据块前需要先读入索引块。若采用链接方案,查找索引块时可能需要很多次读磁盘操作

关于支持随机访问:

  • 文件的某种逻辑结构支持随机存取/随机访问"是指:采用这种逻辑结构的文件,可以根据记录号直接算出该记录对应的逻辑地址(逻辑块号,块内地址)
  • 假设这个文件的逻辑结构是"顺序文件",并且是定长记录,每个记录长度16B
    • 每块大小为1KB,定长记录长度为16B,因此一块有1KB/16B = 64 个记录
    • 逻辑块号m = i / 64,块内地址n = (i % 64) * 16,则i 号记录的逻辑地址= (m, n)
    • 因此,定长记录的顺序文件可以直接算出i 号记录对应的逻辑地址,即支持随机访问

4.5 文件的逻辑结构与物理结构

使用C语言创建一个无结构文件,保证文件为串行数据

FILE *fp = fopne("test.txt","w");   //打开文件
if( fp == NULL){
  printf("打开文件失败!");
  exit(0);
}
//写入1w个Hello world
for(int i=0;i<10000;i++)
  fputs("Hello world!",fp);
fclose(fp);                         //关闭文件

test.txt文件,从用户视角看,即逻辑结构上,每个字符占1B,整个文件占用一片连续的逻辑地址空间

  • 假设查找该文件的第16个字符(编号从0开始)
  • 用户通过逻辑地址去访问文件,对文件内各个数据的存放物理位置不关心
FILE *fp = fopne("test.txt","r");   //以读方式打开文件
if( fp == NULL){
  printf("打开文件失败!");
  exit(0);
}
fseek(fp,16,SEEK_SET);              //读写指针指向16
char c = fgetc(fp);                 //从读写指针所知位置读出一个字符
printf("字符:%c",c);                //打印从文件读出的字符
fclose(fp);                         //关闭文件

test.txt文件,从操作系统视角看,即物理结构上,该文件就是一堆二进制数据,每个磁盘块可存储1KB数据,每个字符占1B,拆分成多个磁盘块存储即可

  • 尽管文件被拆分成多个磁盘块,但逻辑块号是相邻的
  • 用户只需要指明逻辑地址即可访问该文件中的数据
    • 使用 C语言库函数 fseek,将文件读写指针指向位置 n;使用 C语言库函数 fgetc,从读写指针所指位置读出 1B 内容
    • fgetc 底层使用了 Read 系统调用,操作系统将(逻辑块号,块内偏移量)转换为(物理块号,块内偏移量)
  • 对于连续分配方式,逻辑上相邻的块,物理上也相邻
  • 对于链接分配方式,逻辑上相邻的块,物理上通过链接指针表示先后关系
  • 对于索引分配方式,操作系统为每个文件维护一张索引表,其中记录了逻辑块号 -> 物理块号 的映射关系

用C语言创建有结构的顺序文件

typedef struct{
  int number;
  char name[30];
  char major[30];
} Student_info;

//以写方式打开文件
FILE *fp = fopne("test.txt","w");
if( fp == NULL){
  printf("打开文件失败!");
  exit(0);
}
Student_info student[N];            //用数组保存N个学生信息
for(int i=0;i<N;i++){               //生成N个学生信息
  student[i].number=i;
  student[i].name[0]='?';
  student[i].major[0]='?';
}
//将N个学生的信息写入文件
fwrite(student,sizeof(Student_info),N,fp);
fclose(fp);
//以读方式打开文件
FILE *fp = fopne("test.txt","r");
if( fp == NULL){
  printf("打开文件失败!");
  exit(0);
}
//文件读写指针指向编号为5的学生记录
fseek(fp,5*sizeof(Student_inf),SEEK_SET);
Student_inf stu;
//从文件读出1条记录,记录大小为sizeof(Student_inf)
fread(&stu,sizeof(Student_inf),1,fp);
printf("学生编号:%d\n",stu.numer);
fclose(fp);

test.txt文件,从操作系统视角看,即物理结构上,和无结构文件一样,就是一堆二进制数据,使用若干个磁盘块分开存储

  • 从用户视角看,即逻辑结构上,每个学生记录占64B,通过逻辑地址进行访问
  • 对于顺序文件的顺序存储与链式存储
//顺序存储
typedef struct{
  int number;
  char name[30];
  char major[30];
} Student_info;

//链式存储
typedef struct{
  int number;
  char name[30];
  char major[30];
  int next;       //下一个学生记录的存放位置
} Student_info;
  • 顺序存储:各条记录物理上相邻存放,支持随机访问:指可以直接确定第i条记录的逻辑地址
    img
  • 链式存储:各条记录离散着存放,用指针表示先后关系
    img

索引文件:

  • 从用户视角来看,整个文件依然是连续存放的;在操作系统看来,索引表存放在独立的磁盘块中,其他数据离散存放在磁盘中,索引表完成逻辑地址与物理地址的映射
    • 如:前1MB存放索引项,后续部分存放记录

img

typedef struct{
  int number;   //学号
  int addr;     //学生记录的逻辑地址
}IndexTable;

typedef struct {
  char name[30];    //姓名
  char major[30];   //专业
  //还可以添加其他各种学生信息
}Student_info;

4.6 文件的存储空间管理

存储空间的划分:

  • 将物理磁盘划分为一个个文件卷(逻辑卷、逻辑盘)

存储空间的初始化:

  • 将各个文件卷划分为目录区、文件区
  • 文件区:用于存放文件数据
  • 目录区:主要存放文件目录信息FCB、用于磁盘存储空间管理的信息

有的系统支持超大型文件,可支持由多个物理磁盘组成的一个文件卷

4.6.1 文件管理方法

空闲表法:

  • 分配方式:
    • 与内存管理中的动态分区分配很类似,为一个文件分配连续的存储空间
      • 空间表项为首个空闲盘块号以及空闲盘块数
      • 可采用首次适应、最佳适应、最坏适应等算法来决定要为文件分配哪个区间
  • 磁盘块回收:
    • 内存管理中的动态分区分配很类似,当回收某个存储区时需要有四种情况
      • 回收区的前后都没有相邻空闲区
      • 回收区的前后都是空闲区
      • 回收区前面是空闲区
      • 收区后面是空闲区
    • 回收磁盘块时需要注意表项的合并问题
  • 空闲表法适用于连续分配方式

空闲链表法:

  • 操作系统会保存链头和链尾指针,将所有盘块串联成一条链表

  • 空闲盘块链:

    • 以盘块为单位组成一条空闲链
      • 空闲盘块中存储着下一个空闲盘块的指针
    • 分配方式:
      • 若某文件申请 K 个盘块,则从链头开始依次摘下 K 个盘块分配,并修改空闲链的链头指针
    • 磁盘块回收:
      • 回收的盘块依次挂到链尾,并修改空闲链的链尾指针
    • 空闲盘块链适用于离散分配的物理结构,但为文件分配多个盘块时可能要重复多次操作
  • 空闲盘区链:

    • 连续的空闲盘块组成一个空闲盘区,并以盘区为单位组成一条空闲链
      • 空闲盘区中的第一个盘块内记录了盘区的长度下一个盘区的指针
    • 分配方式:
      • 某文件申请 K 个盘块,则可以采用首次适应、最佳适应等算法,从链头开始检索,按照算法规则找到一个大小符合要求的空闲盘区,分配给文件
      • 若没有合适的连续空闲块,也可以将不同盘区的盘块同时分配给一个文件,注意分配后可能要修改相应的链指针、盘区大小等数据
    • 磁盘块回收:
      • 若回收区和某个空闲盘区相邻,则需要将回收区合并到空闲盘区中
      • 若回收区没有和任何空闲区相邻,将回收区作为单独的一个空闲盘区挂到链尾
    • 空闲盘区链对于离散分配、连续分配的方式均适用,为一个文件分配多个盘块时效率更高

位示图法:

  • 位示图:
    • 每个二进制位对应一个盘块
      • 如,0"代表盘块空闲,"1"代表盘块已分配
    • 一般用连续的"字"来表示
      • 如,一个字的字长为16bit,字中的每一位对应一个盘块
      • 可以用(字号,位号)对应一个盘块号,也可描述为(行号,列号)
    • (字号,位号)=(i,j) 的二进制位对应的 盘块号 b = ni + j;b号块对应的字号 i = b/n,位号 j = b%n

注意题目中的盘块号、字号、位号从0开始还是1开始

  • 分配方式:
    • 若文件需要K个块,顺序扫描位示图,找到K个相邻或不相邻的"0"
    • 根据字号、位号算出对应的盘块号,将相应盘块分配给文件
    • 将相应位设置为"1"
  • 磁盘块回收:
    • 根据回收的盘块号计算出对应的字号、位号
    • 将相应二进制位设为"0"
  • 位示图法对于连续分配、离散分配都适用

成组链接法:

  • 空闲表法、空闲链表法不适用于大型文件系统,因为空闲表或空闲链表可能过大。UNIX系统中采用了成组链接法对磁盘空闲块进行管理
  • 文件卷的目录区中专门用一个磁盘块作为"超级块",当系统启动时需要将超级块读入内存,并且要保证内存与外存中的"超级块"数据一致
    • 因此目录块中的读取速度要求快一些

img

  • 每个超级块包含下一组空闲盘块数以及下一组中空闲盘块号清单

    • 每个分组的盘块数量是有限制的,且最后一个空闲盘块分组的空闲盘块数一般比其他分组数量要少
    • 超级块中空闲块表首项作为下一分组的头,存放再下一组的空闲盘块数以及下一组中空闲盘块号清单
    • 依次类推,将所有空闲盘块构成一条分组链表
  • 若某空闲盘块后没有下一组空闲盘块时,空闲块表首项块号设置特殊值

  • 分配方式:

    • 需要分配1个空闲块:
      • 检查第一个分组的空闲块数是否足够。假设分组最大盘块数量为100,1<100,因此是足够的
      • 分配第一个分组中的1个空闲块,并修改相应数据。从第一个分组中删去被分配的空闲块(表首项最后删除),下一组空闲盘块数-1
    • 需要分配100个空闲块:
      • 检查第一个分组的块数是否足够。100=100,是足够的
      • 分配第一个分组中的100个空闲块
      • 但是由于300号块内存放了再下一组的信息,因此300号块的数据需要复制到超级块中
      • 超级快直接首项指向下一组400,300块所在分组删去

    img

  • 磁盘块回收:

    • 假设每个分组最多为100个空闲块,此时第一个分组已有99个块,还要再回收一块
      • 直接在第一个分组增加回收的盘块号,该分组下一组空闲盘块数+1
    • 假设每个分组最多为100个空闲块,此时第一个分组已有100个块,还要再回收一块
      • 需要将超级块中的数据复制到新回收的块中,并修改超级块的内容,让新回收的块成为第一个分组
      • 则第一个分组,下一组空闲盘块数为1,首项指向新回收的块号

    img

4.7 文件的基本操作

创建文件:Create 系统调用

  • 包括以下参数
    1. 所需的外存空间大小(如:一个盘块,即1KB)
    2. 文件存放路径("D:/Demo")
    3. 文件名(这个地方默认为"新建文本文档.txt")
  • 进行Create系统调用,执行以下过程:
    1. 在外存中找到文件所需的空间

      如空闲链表法、位示图、成组链接法等管理策略,找到空闲空间

    2. 根据文件存放路径的信息找到该目录对应的目录文件(此处就是D:/Demo 目录),在目录中创建该文件对应的目录项。目录项中包含了文件名、文件在外存中的存放位置等信息

删除文件:Delete 系统调用

  • 包括以下参数
    1. 文件存放路径("D:/Demo")
    2. 文件名("test.txt")
  • 进行Delete系统调用,执行以下过程:
    1. 根据文件存放路径找到相应的目录文件,从目录中找到文件名对应的目录项
    2. 根据该目录项记录的文件在外存的存放位置、文件大小等信息,回收文件占用的磁盘块

      回收磁盘块时,根据空闲表法、空闲链表法、位图法等管理策略的不同,需要做不同的处理

    3. 从目录表中删除文件对应的目录项

打开文件:Open 系统调用

  • 很多操作系统,在对文件进行操作前,要求用户先执行open系统调用
  • 包括以下参数
    1. 文件存放路径("D:/Demo")
    2. 文件名("test.txt")
    3. 要对文件的操作类型(如:r 只读;rw 读写等)
  • 进行Open系统调用,执行以下过程:
    1. 根据文件存放路径找到相应的目录文件,从目录中找到文件名对应的的目录项,并检查该用户是否有指定的操作权限
    2. 将目录项复制到内存中的"打开文件表"中。并将对应表目的编号返回给用户。之后用户使用打开文件表的编号来指明要操作的文件

打开文件时并不会把文件数据直接读入内存。执行系统调用后,会将打开文件表的"索引号"返回给用户,索引号也称"文件描述符"

img

  • 当执行完open系统调用后,原先存储在外存中的目录信息就被复制到执行进程中,即复制到了主存中,后续对文件操作不需要重新查询目录,可以加快文件的访问速度
    img
  • 其中打开文件表有两种
    • 系统打开文件表:整个系统只有一张,记录所有处于打开的文件清单
    • 用户进程的打开文件表:每个进程各有一张,表项系统表索引号指向该文件在系统打开文件表的编号

关闭文件:Close 系统调用

  • 该系统调用只需要指明打开文件表中的索引号即可
  • 进行Close系统调用,执行以下过程:
    1. 根据文件存放路径找到相应的目录文件,从目录中找到文件名对应的的目录项,并检查该用户是否有指定的操作权限
    2. 将目录项复制到内存中的"打开文件表"中。并将对应表目的编号返回给用户。之后用户使用打开文件表的编号来指明要操作的文件

读文件:Read 系统调用

  • 包括以下参数:
    1. 文件索引号
    2. 要读入多少数据(如:读入1KB)
    3. 读入的数据要放在内存中的什么位置
  • 进行Read 系统调用,执行以下过程:
    • 从读指针指向的外存中,将用户指定大小的数据读入用户指定的内存区域中

写文件:Write 系统调用

  • 包括以下参数:
    1. 文件索引号
    2. 要写出多少数据(如:读入1KB)
    3. 写回外存的数据放在内存中的什么位置
  • 进行Read 系统调用,执行以下过程:
    • 从用户指定的内存区域中,将指定大小的数据写回写指针指向的外存

读/写文件"用"文件描述符"即可指明文件,不再需要用到"文件名"

4.8 文件共享

文件共享:

  • 操作系统为用户提供文件共享功能,可以让多个用户共享地使用同一个文件
  • 多个用户共享同一个文件,意味着系统中只有"一份"文件数据。并且只要某个用户修改了该文件的数据,其他用户也可以看到文件数据的变化
  • 如果是多个用户都"复制"了同一个文件,那么系统中会有"好几份"文件数据。其中一个用户修改了自己的那份文件数据,对其他用户的文件数据并没有影响

基于索引结点的共享方式:硬链接

  • 由于检索文件时只需用到文件名,因此可以将除了文件名之外的其他信息放到索引结点中
  • 索引结点中设置一个链接计数变量count,用于表示链接到本索引结点上的用户目录项数
    • 若count = 2,说明此时有两个用户目录项链接到该索引结点上,或者说是有两个用户在共享此文件
    • 若某个用户决定"删除"该文件,则只是要把用户目录中与该文件对应的目录项删除,且索引结点的count值减1
    • 若count>0,说明还有别的用户要使用该文件,暂时不能把文件数据删除,否则会导致指针悬空
    • 文件被创建时,count初值为1;当count = 0 时系统负责删除文件

基于符号链的共享方式:软链接

  • 创建一个新的特殊文件,Link类型文件,该文件记录了想要共享的文件的存放路径,类似于windows系统的快捷方式
    • Link类型的文件名可以与原始文件不同
    • Windows系统中双击打开Link文件时,操作系统判断这个文件是Link类型的"快捷方式"文件,于是会根据其中记录的"路径信息"检索目录,最终找到"QQScLauncher.exe"
  • 当用户访问这个特殊文件时,操作系统判断文件属于Link类型文件,会根据其中记录的路径检索查找路径,找到该路径目录表中该文件的表项,从而找到该文件的索引节点

img

如果Link文件锁链接的文件索引节点被删除了,即记录中的存放路径已经无法到该文件

  • 但Link文件并不会发生任何变化,只是通过该文件的路径去查找共享文件会失败
  • 软连接方式访问共享文件时,要查询多级目录,会产生多次磁盘I/O,因此软链接访问共享文件速度比硬链接更慢

4.9 文件保护

文件保护是文件系统提供的功能,用于保护文件数的安全,分为以下几种方式:

  • 口令保护

    • 为文件设置一个"口令"(如:abc112233),用户请求访问该文件时必须提供"口令"
    • 口令一般存放在文件对应的 FCB 或索引结点中
      • 用户访问文件前需要先输入"口令",操作系统会将用户提供的口令与FCB中存储的口令进行对比
      • 如果正确,则允许该用户访问文件
    • 优点:
      • 保存口令的空间开销不多,验证口令的时间开销也很小
    • 缺点:
      • 正确的"口令"存放在系统内部,不够安全
  • 加密保护

    • 使用某个"密码"对文件进行加密,在访问文件时需要提供正确的"密码"才能对文件进行正确的解密
      • 一个最简单的加密算法——异或加密,假设用于加密/解密的"密码"为01001
      • 文件的原始数据为0010 1011 0001 1101 0001
      • 加密密码为0100 1010 0101 0010 1001
      • 加密结果为0110 0001 0100 1111 1000
      • 若采用的解密密码为0100 1010 0101 0010 1001,解密结果则为0010 1011 0001 1101 0001
      • 若采用的是不一致的解密密码0111 1011 1101 1110 1111,则解密结果为0001 1010 1001 0001 0111
    • 优点:
      • 密性强,不需要在系统中存储"密码"
    • 缺点:
      • 编码/译码,或者说加密/解密要花费一定时间
  • 访问控制

    • 在每个文件的FCB(或索引结点)中增加一个访问控制列表 ACL,Access-Control List,该表中记录了各个用户可以对该文件执行哪些操作
    • 访问类型权限
    权限类型 权限描述
    从文件中读数据
    向文件中写数据
    执行 将文件装入内存并执行
    添加 将新信息添加到文件结尾部分
    删除 删除文件,释放空间
    列表清单 列出文件名和文件属性
    • 某文件的访问控制列表
    用户 执行 添加 删除 列表清单
    father 1 1 1 1 1 1
    mother 1 0 1 0 0 1
    son 0 0 0 0 0 0
    • 有的计算机可能会有很多个用户,因此访问控制列表可能会很大,可以用精简的访问列表解决这个问题
    • 精简的访问列表:
      • "组"为单位,标记各"组"用户可以对文件执行哪些操作

        如:分为 系统管理员、文件主、文件主的伙伴、其他用户 几个分组

      • 当某用户想要访问文件时,系统会检查该用户所属的分组是否有相应的访问权限
      • 若想要让某个用户能够读取文件,只需要把该用户放入"文件主的伙伴"这个分组即可
    权限分组 完全控制 执行 修改 读取 写入
    系统管理员 1 1 1 1 1
    文件所属用户 0 1 1 1 1
    文件所属的伙伴 0 1 0 1 0
    其他用户 0 0 0 0 0
    • 优点:
      • 实现灵活、可以实现复杂的文件保护

4.10 文件系统的层次结构

自上而下的文件系统层次结构:
img

  • 用户接口:文件基本操作
    • 文件系统需要向上层的用户提供一些简单易用的功能接口
    • 这层就是用于处理用户发出的系统调用请求(Read、Write、Open、Close 等系统调用)
  • 文件目录系统:文件目录
    • 用户是通过文件路径来访问文件的,因此这一层需要根据用户给出的文件路径找到相应的FCB或索引结点
    • 所有和目录、目录项相关的管理工作都在本层完成
      • 如:管理活跃的文件目录表、管理打开文件表等
  • 存储控制模块:文件保护
    • 为了保证文件数据的安全,还需要验证用户是否有访问权限。这一层主要完成了文件保护相关功能
  • 逻辑文件系统与文件信息缓冲区:文件逻辑结构
    • 用户指明想要访问文件记录号,这一层需要将记录号转换为对应的逻辑地址
  • 物理文件系统:文件物理结构
    • 这一层需要把上一层提供的文件逻辑地址转换为实际的物理地址
  • 辅助分配模块:文件存储空间管理
    • 负责文件存储空间的管理,即负责分配和回收存储空间
  • 设备管理模块:I/O外部设备管理
    • 直接与硬件交互,负责和硬件直接相关的一些管理工作
    • 如:分配设备、分配设备缓冲区、磁盘调度、启动设备、释放设备等

实际例子:假设某用户请求删除文件"D:/工作目录/学生信息.xlsx" 的最后100条记录

  1. 用户接口:
  • 用户需要通过操作系统提供的接口发出上述请求
  1. 文件目录系统:
  • 由于用户提供的是文件的存放路径,因此需要操作系统一层一层地查找目录,找到对应的目录项
  1. 存取控制模块(存取控制验证层):
  • 不同的用户对文件有不同的操作权限,因此为了保证安全,需要检查用户是否有访问权限
  1. 逻辑文件系统与文件信息缓冲区:
  • 验证了用户的访问权限之后,需要把用户提供的"记录号"转变为对应的逻辑地址
  1. 物理文件系统:
  • 知道了目标记录对应的逻辑地址后,还需要转换成实际的物理地址
  1. 设备管理程序模块:
  • 要删除这条记录,必定要对磁盘设备发出请求
  1. 辅助分配模块:
  • 删除这些记录后,会有一些盘块空闲,因此要将这些空闲盘块回收

4.11 文件系统布局

img
原始磁盘空间为一整段连续空间,经过物理格式化以后,划分出各个扇区

  • 物理格式化:低级格式化

    • 划分扇区,检测坏扇区,并用备用扇区替换坏扇区

    用户常用的是高级格式化,即逻辑格式化

    物理格式化一般是磁盘出厂前所作的操作,需要使用专业软件进行,且重复的物理格式化可能会减少磁盘寿命。一旦使用低级格式化,会清楚磁盘中的所有数据,即使使用专用恢复软件也无法恢复磁盘数据

    • 由于硬盘在格式化划分扇区时,会划分一部分备用扇区,当检测到了坏扇区时用备用扇区进行替换
    • 操作系统对于使用坏扇区还是备用扇区是透明的,由磁盘自己完整该功能

磁盘空间换分出扇区后,可进行逻辑格式化,将磁盘进行分区/卷,完成各分区的文件系统初始化

  • 逻辑格式化:高级格式化
    • 将磁盘进行按分区(分卷Volume)进行二次划分,每个分区可以建立独立的文件系统

img

  • 逻辑格式化后,灰色部分就有实际数据了,白色部分还没有数据
  • 逻辑格式化过程其实是包含在操作系统安装的过程中,因此逻辑格式化会顺带在每个分区/卷建立文件系统,即先有操作系统才会有文件系统
  • 主引导记录用于电脑开机时,将操作系统引入到主存中的一个独立分区

4.11.1 文件系统在内存中的结构

内存中分为用户区和内核区,磁盘在用户区、内核区存储的信息不相同
img

  • 近期进程范文过的目录文件会缓存在内存的内核区中,这样就不需要每次都从磁盘中读入,以加快目录检索速度
  • 内存内核区还会存放系统打开文件表和进程打开文件表,系统打开文件表只有一张,进程打开文件表一个进程对应一张
    • 进程打开文件表存储在进程的PCB中

发生open系统调用时,打开文件的过程:
img

  • 以只读方式执行open系统调用,检索M目录下的A文件,CPU在磁盘中找到M目录读入主存的目录缓存中
  • 在主存目录缓存中查找A文件的FCB,找到FCB后复制到系统打开文件表,表示文件已被打开,并计数1
  • 同时将该FCB复制到执行系统调用的文件进程的进程打开文件表中,设定打开方式为只读,并将系统打开表中该文件的索引号复制到进程打开文件表中
  • 在进程打开文件表新建该表项后,意味着文件打开命令执行完成,返回给用户一个文件描述符
  • 文件描述符可用于后续read、write等系统调用指明对哪个文件进行操作
  • read、write系统调用接收到文件描述符后,会在进程文件打开表中找到相应的文件,再通过系统打开文件表索引找到文件的FCB
  • 获得了FCB,就可以获得文件在磁盘中的存储物理位置,从而对文件进行操作

4.12 虚拟文件系统

传统文件系统,一般所使用的文件系统操作规范各不相同

  • 程序员在编写应用程序的时候如果考虑适配不同的文件系统,需要编写多套代码去实现系统调用过程,极大增大应用程序开发成本
    • 如,UFS文件系统打开文件使用open(a,b)函数;NTFS文件系统打开文件使用fopen(x)函数;FAT文件系统打开文件使用openf(p,q)函数
  • 同时不同文件系统的文件数据结构也并不相同,打开文件后,其文件数据在内存中的表示方式也不同
    • 如,UFS文件系统的目录项为文件名 + i节点号;FAT文件系统的目录项为文件名 + 文件类型 + 文件大小 + 起始块号 + 其他字段...

img

虚拟文件VFS,virtual File System:

  • 向上层用户进程提供统一标准的系统调用接口,屏蔽底层具体文件系统的实现差异
  • VFS要求下层的文件系统必须实现某些规定的函数功能
    • 如:open/read/write
    • 一个新的文件系统想要在某操作系统上被使用,就必须满足该操作系统VFS的要求
  • 每打开一个文件,VFS就在主存中新建一个vnode,用统一的数据结构表示文件,无论该文件存储在哪个文件系统
    img
    • vnode,即v节点数据结构中一般包括文件名、文件大小、创建者、文件格式、函数功能指针等字段
    • vnode只存在于主存中,而如UFS文件系统中的inode节点信息既会被调入主存,也会在外存中存储
    • 打开文件后,VFS会创建vnode,并将文件信息复制到vnode中,vnode的功能指针指向具体文件系统的函数功能

4.12.1 文件系统挂载

文件系统挂载,mouting:

  • 即文件系统安装/装载,一般指将文件系统挂载到操作系统中
    • 如,电脑插入U盘,就是将U盘的文件系统挂载在当前操作系统中
  • 文件系统挂载过程:
    • 在VFS中注册新挂载的文件系统
      • 内存中的挂载表mount table包含每个文件系统的相关信息,包括文件系统类型、容量大小等
    • 新挂载的文件系统,要向VFS提供一个函数地址列表
    • 将新文件系统加到挂载点mountpoint,也就是将新文件系统挂载在某个父目录下
      • 对于windows系统而言,新挂载的文件系统以独立的盘符形式存在,即独立分卷
      • 对于MAC系统,新挂载的文件系统会存放在根目录的Volumes目录中,即/Volumes
      • 对于linux,可以使用mount指令,将挂载的文件系统直接覆盖在指定的一个目录上(如/mnt/disk),原操作系统该目录的信息会隐藏,直到该挂载文件系统卸载才会恢复
posted @ 2024-09-05 22:37  GK_Jerry  阅读(105)  评论(0)    收藏  举报