操作系统笔记(王道考研) 第四章:文件管理

大部分内容基于中国大学MOOC的2021考研数据结构课程所做的笔记,后续又根据2023年考研的大纲增加了一些内容,主要有操作系统引导、虚拟机、多级队列调度算法、互斥锁、调度器和闲逛进程、内存映射文件、文件系统的全局结构、虚拟文件系统、固态硬盘SSD、输入输出应用程序接口 、驱动程序接口等等。

感谢我的室友HXN,他帮我写了一部分第五章的内容。

课程内容和西电平时讲课的内容大致重合,西电可能每章会多讲一点UNIX系统的实例,可以听完这课再快速过一遍老师的课件防止漏掉什么内容。

这门课讲的其实不算特别硬核,没怎么涉及具体的代码。不过我其实感觉操作系统是个大无底洞,能学到多深基本取决于愿意花多少时间和精力。如果有闲心,推荐看下南大蒋炎岩老师的《操作系统:设计与实现》和哈工大李治军老师的《操作系统》,讲的更深入,当然难度也相应的大的多。

 

其他各章节的链接如下:

操作系统笔记(王道考研) 第一章:计算机系统概述

操作系统笔记(王道考研) 第二章:进程管理(1)

操作系统笔记(王道考研) 第二章:进程管理(2)

操作系统笔记(王道考研) 第三章:内存管理

操作系统笔记(王道考研) 第四章:文件管理

操作系统笔记(王道考研) 第五章:输入输出(I/O)管理

其他各科笔记汇总

文件管理

初识文件管理

image-20210503103648130

前情回顾

image-20210503100626933

操作系统作为系统资源的管理者也需要对文件进行管理,文件也属于一种系统资源。

Word,PPT,PDF文档等等都是文件,各种各样的文件在我们面前呈现出不同的特性,操作系统需要关心这些特性。不同文件有不同的属性,故在使用文件的时候会有各种各样的差别

文件的属性

image-20210503101758983

image-20210503102205321

在一个系统当中肯定是有很多重名文件的,只是在同一文件夹下不允许有重名的文件,故用文件名并不能唯一地区分出每一个文件到底是哪一个。因此操作系统会在背后为各个文件设置一个唯一的标识符,标识符一般来说就是一连串数字和字母的组合,对用户来说毫无可读性,所以在上图的界面中也没有向用户展示出一个文件的标识符

这个文件平时是存放在外存也就是磁盘当中的,当我们双击打开这个文件的时候,操作系统需要从外存把文件的数据读入内存,因此操作系统也需要关心文件在外存当中存放的位置,只不过在外存当中存放的地址属性对用户是不可见的,只有操作系统需要关心

操作系统对系统当中的用户进行了分组,不同分组的用户对文件的操作权限是不同的。如果创建的文件不想让别的计算机用户来访问的话,就可以设置一下它的保护信息

文件内部的数据应该怎样组织起来?

image-20210503103736871

无结构文件没有明显的结构特性

 

 

image-20210503103752434

文件之间应该怎样组织起来?

image-20210503104216318

image-20210503104242116

操作系统应该向上提供哪些功能?

image-20210503104901407

点击新建后,图形化交互进程其实是在背后调用了操作系统向上层提供的“create 系统调用”来完成文件创建的工作

创建文件之后,这个文件的数据就在外存当中了

双击test文件之后,操作系统先是默认自动地打开了.txt对应的应用程序,也就是记事本。这个应用程序又调用了操作系统向上提供的“read 系统调用”来实现了读文件的功能

平时我们编辑这个文件的时候,其实只是改变了文件在内存当中的副本的数据

 

image-20210503104920337

从上往下看,文件应如何存放在外存?

image-20210503105006348

操作系统在进行读写文件的时候也是以块为单位进行数据交换的

image-20210503105026874

文件的物理结构探讨的是文件这些数据在物理上是应该怎么存放,怎么组织

文件的逻辑结构指的是文件的各个记录在逻辑上应该是什么样的一种组织关系

其他需要由操作系统实现的文件管理功能

image-20210503110531573

文件的逻辑结构

image-20210503110816343
在这里插入图片描述

 

所谓的“逻辑结构”,就是指在用户看来,文件内部的数据应该是如何组织起来的。而“物理结构”指的是在操作系统看来,文件的数据是如何存放在外存中的

类似于数据结构的“逻辑结构”和“物理结构”

如“线性表”就是一种逻辑结构,在用户角度看来,线性表就是一组有先后关系的元素序列,如:a,b,c,d,e …

“线性表”这种逻辑结构可以用不同的物理结构实现,如:顺序表/链表。顺序表的各个元素在逻辑上相邻,在物理上也相邻;而链表的各个元素在物理上可以是不相邻的。因此,顺序表可以实现“随机访问”,而“链表”无法实现随机访问

可见,算法的具体实现与逻辑结构,物理结构都有关(文件也一样,文件操作的具体实现与文件的逻辑结构,物理结构都有关)

无结构文件

image-20210503123827144

有结构文件

image-20210503142331259

image-20210503142527636

image-20210503142555149

image-20210503142651451

 

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

顺序文件

类比线性表,应该不难理解

image-20210503143015836

image-20210503143054220

若文件的记录是可变长的就必须在每个记录之前用一定的存储空间来表示记录的长度

在实际应用中为了减少磁盘的I/O次数,一般来说操作系统会管理一个日志文件,用该日志文件来记录对这个文件当中的各个记录进行修改的一些信息然后每隔一段比较长的时间再把这些信息统一地合并到外存当中的这个文件数据当中,比如说每隔一个小时才合并一次或者每隔十分钟才合并一次,这样就可以减少对于顺序存储的顺序进行增删改带来的一些开销

索引文件

image-20210503145159681

索引表的各个表项在物理上是需要连续存放的,每一个索引表的表项大小都相等

索引顺序文件

image-20210503150348228

索引顺序文件的顺序表其实是一个定长记录的串结构的顺序文件

索引顺序文件(检索效率分析)

image-20210503150313018

多级索引顺序文件

image-20210503150520359

 

文件目录

image-20210503151356498

 

文件目录就是我们很熟悉的 Windows 操作系统的“文件夹”

 

这种一层一层的目录结构对于用户来说有什么好处?

文件之间的组织结构清晰,易于查找。编程时也可以很方便的用文件路径找到一个文件。如:

FILE *fp;
fp=fopen("F:\data\myfile.dat");

用户可以轻松实现“按名存取”

那从操作系统的角度来看,这些目录结构应该是如何实现的呢?

 

“按名存取”:按照文件的名字来操作一个文件

文件控制块

D,E盘是逻辑磁盘

image-20210503164944088

打开电脑中的D盘根目录,会发现这个根目录下面有一系列的文件夹/文件目录和一些普通的文件。对于D盘这个根目录来说,它对应的目录文件如上图所示。其实就是用一个目录表来表示这个目录下面存放了哪些东西,在D盘当中的每一个文件和文件夹都会对应这个目录表当中的一个表项,这些一条一条的目录项本身就是一条一条的记录

目录文件本身就是一种有结构的文件,我们在这个地方看到的目录其实也是一种特殊的文件

 

image-20210503165004225

 

image-20210503165020406

目录结构 —— 单级目录结构

image-20210503171855272

目录结构 —— 两级目录结构

image-20210503171921879

目录结构——多级目录结构

又称树形目录结构

image-20210503172725900

 

image-20210503172835806

 

image-20210503172903174

目录结构——无环图目录结构

image-20210503173123728

在引用了共享功能之后,对于文件的删除就不能像以前那么简单(只要一个用户让删除一个文件就把这个文件的实际数据给删除),因为这个文件可能被多个用户所使用。为了解决这个问题,可以如上图所示,为每一个共享结点设置一个共享计数器

 

此时如果User1提出删除文件请求,操作系统只会把User1对应的目录项删除,并且让共享计数器减1,而这个文件的实际内容并不会被直接删除

只有共享计数器的值减为0时,就意味着这个文件不再被任何用户所使用,此时才可以把这个共享文件真正地删除

image-20210503173926986

注意如果User1只是复制了一个User2的文件的话,其实它们俩所拥有的文件并不是同一个文件。当User1对自己的文件副本进行修改的时候,原来的文件数据并不会改变。共享文件则不然

索引结点( FCB 的改进)

image-20210503174417967

按照文件名来搜索目录的时候,并不需要关心除了文件名之外的其他所有信息

采用了索引结点这种机制之后,目录当中只包含文件名还有指向索引结点的指针这两个信息

 

image-20210503174437156

 

文件的物理结构(文件的分配方式)

image-20210503195718385

 

操作系统作为最接近硬件的软件层次需要对硬件,包括外存也就是磁盘进行管理。操作系统对磁盘的管理主要需要做两件事:

1.对非空闲磁盘块进行管理(存放了文件数据的磁盘块)

这是这一小节要探讨的“文件的物理结构/文件分配方式”的问题

2.对空闲磁盘块进行管理

这是之后的小节会探讨的“文件存储空间管理”的问题

 

文件物理结构/文件分配方式要探讨的就是文件的数据到底应该怎样存放在外存中,这些数据应该怎样被组织起来的问题

文件块,磁盘块

image-20210503190539177

image-20210503190630744

用户对于自己文件的这些逻辑块到底存放到了什么地方是不可知的,因此用户在操作自己的文件时使用的是(逻辑块号,块内地址)这样的形式。于是操作系统就需要负责把用户提供的逻辑块号和块内地址转换为这个文件块实际存放的物理块号和块内地址

文件分配方式 —— 连续分配

image-20210503191811042

顺序访问:如果要访问逻辑块号2就必须先顺序地访问逻辑块号0和逻辑块号1,之后才能找到逻辑块号2

直接访问(随机访问):如果要访问逻辑块号2并不需要访问其他的块,可以直接找到逻辑块号2存放的位置

image-20210503191859268

读取某个磁盘块的时候需要把磁头放到那个磁盘块相应的位置

 

image-20210503192550675

image-20210503192748250

连续分配(总结)

image-20210503192945444

文件分配方式 —— 链接分配

链接分配采取离散分配的方式,可以为文件分配离散的磁盘块,然后用指针链接的方式把这些磁盘块都给串联起来。分为隐式链接和显式链接两种

链接分配 —— 隐式链接

image-20210503193455853

image-20210503193822888

 

总结如下

image-20210503193848821

链接分配 —— 显式链接

image-20210503194056599

image-20210503194316482

 

总结如下

image-20210503194405854

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

文件分配方式 —— 索引分配

image-20210503211917762

image-20210503211941872

image-20210503212104273

 

1.链接方案

image-20210503212222690

在每个索引块当中用一定的空间存储指向下一个索引块的指针

由于各个索引块之间是用链接的方式连起来的,所以为了找到第2个索引块的块号操作系统需要首先把第1个索引块读入内存,然后才能根据索引块当中的指针找到第2个索引块的块号并且把第2个索引块读入内存

 

2.多层索引

image-20210503212921113

在FCB中只需要记录它的顶级索引表存放的索引块号是多少

若采用三层索引,则文件的最大长度为

256*256*256*1KB=16GB

类似的,访问目标数据块,需要4次磁盘I/O

 

假如有一个文件很小,数据块只有1KB这么大,但是在物理上采用的是两层索引结构,那么读入这个文件1KB的内容依然需要3次读磁盘操作。故多层索引也存在一些小小的问题

 

3.混合索引

image-20210503214257317

索引分配(总结)

image-20210503214631103

 

逻辑结构VS物理结构

image-20210503214837733

本节会举一些具体的例子,把逻辑结构和物理结构当中涉及到的一些很相似的概念进行对比

例:C语言创建无结构文件

image-20210503215221587

如果在代码运行的目录下没有test.txt这个文件,调用fopen函数之后会自动给你新建一个

逻辑结构(从用户视角看)

image-20210503215926100

物理结构(从操作系统视角看)

操作系统会根据它的文件管理策略来决定到底是用连续分配还是其他分配方式把这些文件的数据块存到磁盘里面

操作系统在处理Read系统调用请求时会把fgetc这个函数向它传递的逻辑地址转换为(逻辑块号,块内偏移量)的形式,然后再根据自己的存储分配策略把逻辑块号转换为与之对应的物理块号。这是操作系统在背后帮用户做的事情,对用户来说这些事情是不可知的,也没必要关心。用户作为文件的使用者只需要关心文件里各种各样的数据到底存放在哪一个逻辑地址里

image-20210503220201208

image-20210503220219061

image-20210503220231109

例:C语言创建顺序文件

image-20210503221246839

物理结构(从操作系统视角看)

作为用户只需要能够提供想要访问的记录所存放的逻辑地址,然后剩下的逻辑地址转换为逻辑块号,逻辑块号再转换为物理块号这些事情都是操作系统在背后帮我们完成的

image-20210503224126578

image-20210503224147350

image-20210503224221917

懵逼点:顺序文件采用顺序存储/链式存储

image-20210503224338575

静态链表

用户在创建一个文件的时候可以自己决定到底是用顺序存储的方式还是用链式存储的方式来存放这些记录。但是无论如何在用户的视角看来这些记录肯定都是占用了一整片的连续空间

链式存储的顺序文件采用连续分配…

image-20210503225033330

image-20210503225136895

要会区分文件的逻辑结构里提到的的链式存储和文件的物理结构里提到的链接分配

链式存储指的是在文件内部的那些记录的先后顺序是用链接指针连起来的,这是用户自己来设计的,操作系统并不管

链接分配中链接是操作系统做的事情,用户并不需要管。操作系统会把用户给出的这一整个很大的文件拆分成一个个的逻辑块,然后在磁盘里存放这些逻辑块时操作系统会用链接的方式来记录这些逻辑块之间的先后顺序

逻辑结构:索引文件

image-20210503230404717

这种逻辑结构同样也是由文件的创建者自己来决定的

索引文件采用索引分配

image-20210503230428512

要会区分文件的逻辑结构里提到的的索引文件和文件的物理结构里提到的索引分配

 

文件存储空间管理

image-20210503234331902

在之前的小节中我们学习了文件的物理结构,也就是对非空闲磁盘块的管理。这一小节要学习的对存储空间的管理其实就是对空闲的那些磁盘块的管理

 

存储空间的划分与初始化

image-20210504094751583

像FCB,索引结点这些就是存放在目录区当中的

用于磁盘存储空间管理的那些信息,那些数据结构也是存放在目录区当中的,就比如这一小节接下来会学习的空闲表,位示图之类的数据结构

存储空间管理 —— 空闲表法

适用于“连续分配方式”

 

image-20210504101229810

参考内存管理中的动态分区分配思考系统会如何处理以下情况

Eg:新创建的文件请求3个块,采用首次适应算法

Eg:假设此时删除了某文件,系统回收了它占用的15,16,17号块

存储空间管理 —— 空闲链表法

image-20210504102837107

 

image-20210504102939118

像上例中链头是20号磁盘块,链尾是0号磁盘块

 

image-20210504102954385

存储空间管理 —— 位示图法

连续分配,离散分配都适用

 

image-20210504104158595

image-20210504104222884

存储空间管理 —— 成组链接法

image-20210504104504834

image-20210504104751386

每一个分组的盘块数量有上限

分组的第一个磁盘块还需要记录下一组空闲盘块的一些信息

 

如何分配?

Eg:需要1个空闲块

image-20210504105612745

超级块已经读入内存,进行检查时不需要读磁盘操作

 

image-20210504105755789

 

Eg:需要100个空闲块

image-20210504110111827

image-20210504110509676

image-20210504110833155

超级块其实充当了链头的作用,在这个链头当中永远要保持指向下一个分组的一些信息

 

如何回收?

Eg:假设每个分组最多为100个空闲块,此时第一个分组已经有99个块,还要回收一块

image-20210504111516032

image-20210504111735894

 

Eg:假设每个分组最多有100个空闲块,此时第一个分组已有100个块,还要再回收一块

image-20210504112023422

image-20210504112226283

image-20210504112349256

把超级块当中的内容复制到新回收的块当中,这样新回收的块作为一个新的分组就拥有了指向下一个分组的这些链接的指针。由于超级块永远要指向第一个分组,所以要修改超级块的数据,让它指向第一个分组即新的回收块组成的新分组

image-20210504112904163

 

文件的基本操作

image-20210503231151972

 

创建文件

image-20210503231308096

删除文件

image-20210503231337929

打开文件

image-20210503231425165

根据提供的文件存放路径在外存当中找到这个目录对应的目录表

用户对文件的访问权限的信息也是记录在目录项当中的,如果没有操作权限的话就可以拒绝用户打开文件终止处理

打开文件时并不会把文件的数据直接读入内存,只是把文件的目录项复制到内存的打开文件表当中

 

image-20210503231519054

系统的打开文件表会记录所有的正在被其他进程使用的文件的一些信息

每个进程也会有自己的打开文件表

关闭文件

image-20210503233455423

读文件

image-20210503231824566

在对文件进行读写操作之前一定要先打开文件

这些参数的填充都是记事本这个进程在背后为用户完成的

写文件

image-20210503231856812

文件共享

image-20210504125840699

 

操作系统为用户提供文件共享功能,可以让多个用户共享地使用同一个文件

注意:多个用户共享一个文件,意味着系统中只有“一份”文件数据。并且只要某个用户修改了该文件的数据,其他用户也可以看到文件数据的变化

如果是多个用户都“复制”了同一个文件,那么系统中会有“好几份”文件数据。其中一个用户修改了自己的那份文件数据,对其他用户的文件数据并没有影响

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

image-20210504130616727

image-20210504130740350

image-20210504130822404

image-20210504130920151

image-20210504131119086

image-20210504131015828

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

image-20210504131430461

存放路径也可以保存为“C:/User2/bbb”

 

来看一下Windows操作系统当中快捷方式的例子

image-20210504131857923

image-20210504131920773

 

假设此时User1和User2都不再需要使用文件1,由于此时count值变为了0,因此这个文件还有它的索引结点就可以直接被删除了

image-20210504132319512

 

还是结合Windows操作系统为例

image-20210504132441398

 

文件保护

image-20210504132606811

 

操作系统需要保护文件的数据安全

口令保护

image-20210504145513387

当用户想要访问一个文件时操作系统无论如何肯定要找到这个文件对应的FCB或者索引结点

加密保护

image-20210504145921613

image-20210504150734154

用密码和文件的原始数据依次做异或运算

系统当中保存的并不是文件的原始数据,而是对文件进行加密之后的这一份数据

访问控制

不同系统对操作类型的划分不一样

image-20210504150826255

image-20210504150845636

每一个用户都会从属于其中的一个或者两个分组,操作系统需要记录哪一个用户是属于哪一个分组

如果说这个文件主想要让某个用户也拥有读的权限的话,那么就可以由文件主把这个用户放到“文件主的伙伴”这个分组当中

Windows的访问控制

首先我们可以给自己的Windows电脑添加一个新的本地账户。像Windows10就可以在设置当中找到添加一个账户的选项

依次选择红框部分

会跳出一个让我们建立一个新的账户的页面, 因为要创建的是本地账户,所以点“添加一个没有Microsoft账户的部分”

在弹出的界面中可以输入想要设置的新账户的账户名,比如说“临时访客”

image-20210504152021865

 

点下一步确认后,就可以在“家庭和其他成员”这个地方看到“临时访客”这个本地账户了

image-20210504152802196

 

接下来可以随便打开电脑当中的一个文件或者文件夹,右键选择属性。然后在“安全”页签里可以看见Windows对各种用户的分组还有各个用户实行访问控制的界面

image-20210504153353972

 

如果不想让“临时访客”用户访问“照片”文件夹,则

image-20210504153722582

image-20210504153744214

“临时访客”用户本来属于Users分组,Users分组本来是允许读取文件信息的,但我们又在”临时访客“这选择了拒绝读取这个文件,由于拒绝项的优先级高于允许项,所以虽然”临时访客“也属于Users分组,但是操作系统依然会认为“临时访客”这个用户不允许读取这个文件这个目录

 

切换成“临时访客”用户后,会发现无法打开“照片”文件夹

image-20210504153757691

 

文件系统的层次结构

在这里插入图片描述

image-20210504221307358

文件系统的层次结构

image-20210504221333566

用户接口这一层要做的事情就是之前在”文件的基本操作“那一小节介绍的那些东西

打开一个文件无非就是把那个文件对应的目录项复制到打开文件表当中

如果采用索引文件这种逻辑结构,会为文件当中的各个记录建立一个索引表,为了查询到这些记录对应的逻辑地址就需要查询索引表,而在查询文件的索引表之前就需要先把索引表调入到内存的文件信息缓冲区当中

之前提到的所有这些准备最后都是为了操作外存或者说磁盘上的一些数据

 

不同层次与对应的小节:

用户接口 —— 文件的基本操作

文件目录系统 —— 文件目录

存取控制模块 —— 文件保护

逻辑文件系统与文件信息缓冲区 —— 文件的逻辑结构

物理文件系统 —— 文件的物理结构

辅助分配模块 —— 文件的存储空间管理

设备管理模块 —— 之后磁盘管理相关的那些小节

 

“文件系统实例” 一节无课件,记笔记比较困难。故此处略过不计

该节主要是用OneNote通过画一个很直观的例子把之前学的抽象的内容串起来。考试不可能考这么复杂和这么综合的问题,有兴趣可以自己去看视频

 

文件系统的全局结构(布局)

从一个磁盘出厂,物理格式化再到逻辑格式化来认识文件系统在外存当中是如何一步步被建立的

原始磁盘

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rpY1z8aZ-1662215929383)(操作系统.assets/image-20220903172025394.png)]

物理格式化后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hWbbgAhj-1662215929386)(操作系统.assets/image-20220903172047968.png)]

一个磁盘刚被生产出来时,里面没有被划分扇区,首先要低级格式化

坏扇区的存在对于操作系统来说是透明的,假设操作系统要访问某编号坏扇区,由于磁盘驱动器在物理格式化之后知道这是一个坏扇区,它会在背后用备用扇区替代

逻辑格式化后

逻辑格式化会把磁盘分为一个个分区。每个分区的大小和地址范围用分区表记录

在每个分区当中可以建立各自独立的文件系统,如可以在C盘建立UNIX文件系统

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2rcTuf6P-1662215929388)(操作系统.assets/image-20220903203151311.png)]

位示图可以迅速地判断某一个特定的磁盘块此时是否空闲,而超级块的作用更多的是要迅速地找到若干个空闲的盘块。这两个数据结构在功能上有一定的重合性,都可以标记哪些盘块空闲,但是二者在实际使用中会有一些区别

i i i结点就是索引结点。每一个文件都会有一个与之对应的索引结点,UNIX文件系统当中所有的索引结点都连续存放在 i i i结点区

索引结点在这个区域是连续存放的,而且每一个索引结点的大小都相同,可以认为这个区域就是一个超大的数组,而数组的元素就是一个个索引结点,可以通过一个索引结点的下标迅速地定位到一个指定的索引结点

根目录也会被建立起来,因为任何一个文件系统都必须从一个根目录出发建立新的下一级目录或者存储新的文件

文件系统在外存中的结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F6jftTFZ-1662215929390)(操作系统.assets/image-20220903203242510.png)]

文件系统在内存中的结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ma72B3K-1662215929391)(操作系统.assets/image-20220903203318522.png)]

最近访问过的一些目录的数据会被暂时缓存在内存当中。比如最近查找过目录M由于查找目录M需要把这个目录的数据,也就是目录当中包含的这些FCB都读入主存。如果接下来一段时间内又访问到目录M就没有必要再从外存读入

系统打开文件表整个系统只有一张,而进程打开文件表每个进程有一张,包含在每个进程的PCB当中

 

用一个例子来梳理一下这些东西是怎么工作的

open系统调用打开文件的背后过程
  1. 用open系统调用尝试打开M目录下的A文件(…/M/A)。找到文件A存放的目录M并把目录M的数据读入主存缓存起来

  2. 一个个检查目录项FCB,发现其中有一个目录项的文件名和要找的文件A对得上,把文件A的FCB复制到系统打开文件表当中表示这个文件被打开,同时设置打开计数为1,这意味着当前有一个进程正在使用文件A

  3. 发起open调用的进程在进程打开文件表当中新建条目,其中记录打开方式,进程打开文件表当中不会保存文件A的FCB,只会有一个指向系统打开文件表的索引

    同时给程序员返回一个文件描述符fd,可以简单地理解为这个文件描述符fd就是指向进程打开文件表的一个指针,通过文件描述符fd就可以对打开的文件A进行相应的操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CYL8QlVi-1662215929393)(操作系统.assets/image-20220903205603889.png)]

比如接下来要通过read系统调用对文件A执行读操作。就只需要传入文件描述符fd,同时指明要读多少个字节,要读到什么位置。操作系统在接收到read系统调用后就可以根据文件描述符fd首先去进程文件打开表当中找到对应的条目,然后再根据索引信息找到系统打开文件表当中对应的条目,再从该条目中找到这个文件的FCB,通过FCB操作系统就可以确定文件A在外存当中的存放位置

 

虚拟文件系统

普通的文件系统

使用计算机时会插上各种各样的外部存储设备,如移动硬盘和U盘等。不同的存储设备里面的文件系统格式可能各不相同,不同的文件系统开发者可能会定义不同的函数接口,这对上层的程序员很麻烦

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3bYLNoP-1662215929394)(操作系统.assets/image-20220903210148604.png)]

因此操作系统内核应该向上层的用户进程提供一个统一标准的函数调用接口,所以在操作系统当中引入VFS

虚拟文件系统

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uGGyloJi-1662215929396)(操作系统.assets/image-20220903211200169.png)]

像Linux里就是按照POSIX标准定义的接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PsVTB7z6-1662215929398)(操作系统.assets/image-20220903211221199.png)]

 

UFS文件系统和FAT文件系统的目录项格式有很大差别,UFS文件系统的每一个目录项只包含文件名和 i i i结点编号,需要根据 i i i结点编号把对应 i i i结点读入主存,然后才可以知道这个文件的一些具体信息,而对于FAT文件系统只要读入某一个文件的目录项,这个FCB里就包含了关于文件的所有信息

这就造成了一个新的问题:VFS在内存当中必须使用不同的数据结构来表示来自不同文件系统的文件信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fo5AErlX-1662215929399)(操作系统.assets/image-20220903211920807.png)]

为了解决这个问题,每当打开一个文件之后,VFS就会给这个文件在主存当中新建一个vnode,里面包含文件的各种信息。无论文件存放在哪一种文件系统当中,打开后都会把文件的相关信息复制到vnode当中,这样VFS就可以用一个统一的数据结构vnode来表示任何一个文件的信息

如果此时要打开的文件刚好在UFS文件系统当中,找到这个文件对应的目录项之后会把文件的inode从外存先读入主存,inode的各种信息会被复制到vnode当中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JjXyBGU4-1662215929400)(操作系统.assets/image-20220903212614711.png)]

vnode当中的函数功能指针指向了对应文件系统的函数功能列表。打开文件之后要对文件进行任何操作都可以先找到这个文件的vnode,然后根据vnode当中记录的函数功能指针找到具体对应文件系统的函数功能列表,然后去执行具体的函数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aa2Sh8Pj-1662215929401)(操作系统.assets/image-20220903220920274.png)]

文件系统挂载(mounting)

比如把一个U盘插到电脑上,U盘的文件系统就需要挂载到操作系统的VFS里面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4F7wYjNk-1662215929404)(操作系统.assets/image-20220903222027165.png)]

VFS管理挂载表,上图中挂载了UFS、NTFS、FAT三个文件系统,在VFS的挂载表当中就会有三个表项,分别指向三个文件系统

函数地址列表也就是上面所说的函数功能列表,指明各个系统调用的代码实现存放在什么位置

一个新加入的文件系统需要挂载到某个特定的位置,它可以在某一个原本存在的父目录的下面,接下来才可以访问和使用这个文件系统

什么是挂载点?

如果是Windows系统,每一个盘会用不同的编号(如C、D、E、H、G等等),当插入一个U盘时会发现界面上有一个新的盘符编号来标识一个新的文件系统,新挂载的文件系统的挂载点就是这个地方,和C盘、D盘这些是平级的关系

如果是MAC系统,当插入一个U盘时,在系统根目录下的Volume文件夹,在这个目录下会看到新挂载的文件系统。所以对于MAC系统,这个新文件系统的挂载点就在根目录下面的Volume目录之下
在这里插入图片描述

 

磁盘的结构

image-20210504225205428

磁盘,磁道,扇区

image-20210504230537664

如何在磁盘上读/写数据

image-20210504230650047

磁头会由磁头臂带动,磁头的移动位置只有固定的两个方向

磁盘是由很多个盘片垒起来的

盘面,柱面

image-20210504231106319

一个盘片正面可以是一个盘面,背面也可以是一个盘面

磁盘的物理地址

image-20210504234207964

磁盘的分类

image-20210504234257587

image-20210504234329768

 

磁盘调度算法

在这里插入图片描述

一次磁盘读/写操作需要的时间

image-20210504234505988

image-20210504234525102

image-20210504234547585

image-20210504234611197

先来先服务算法(FCFS)

image-20210504235818293

最短寻找时间优先(SSTF)

image-20210504235718585

扫描算法(SCAN)

image-20210504235429277

LOOK 调度算法

image-20210504235450111

循环扫描算法(C-SCAN)

image-20210504235535929

C-LOOK 调度算法

image-20210504235618890

 

减少延迟时间的方法

image-20210504235927006

 

前情回顾

image-20210505001024413

读完一个扇区之后,磁头需要有一小段时间做中间的准备,在这段时间内磁头不能读入任何数据

连续读入逻辑上相邻的几个扇区号对应的扇区需要转动好几圈磁盘,延迟时间会特别长

减少延迟时间的方法:交替编号

image-20210505000948655

磁盘地址结构的设计

image-20210505001102446

( 00 , 000 , 000 ) ∼ ( 00 , 000 , 111 ) (00,000,000)\sim(00,000,111) (00,000,000)(00,000,111):0号盘面的0号柱面的8个扇区

根据之前的分析知道,在转了一圈之后磁头可以依次读入0,1,2,3这几个扇区的数据。在转第二圈之后这个磁头又可以依次读入4,5,6,7这几个编号对应的扇区里的数据

启动磁头臂还有移动磁头是一种物理上的移动,它所花费的时间是比较高的

image-20210505001156046

( 000 , 00 , 000 ) ∼ ( 000 , 00 , 111 ) (000,00,000)\sim(000,00,111) (000,00,000)(000,00,111):0号盘面的0号柱面的8个扇区

( 000 , 01 , 000 ) ∼ ( 000 , 01 , 111 ) (000,01,000)\sim(000,01,111) (000,01,000)(000,01,111):1号盘面的0号柱面的8个扇区

image-20210505001258207

减少延迟时间的方法:错位命令

image-20210505001339421

假设此时要读取物理地址为0的扇区到物理地址为8的扇区(即 ( 000 , 00 , 000 ) ∼ ( 000 , 01 , 000 ) (000,00,000)\sim(000,01,000) (000,00,000)(000,01,000)

首先要读取0号盘面最内侧磁道的所有扇区。故首先要把0号盘面的磁头激活,然后让磁盘开始旋转,旋转的过程中进行读写。通过之前的分析知道,它需要转两圈才可以把最内测的磁道读完,转了两圈后磁头指向的位置和开始时一样

但是之前说过在读取完一个扇区之后需要有一小段时间进行处理,并不能立即读取下一个扇区,而磁盘又是在不停旋转的,所以在读完了0号盘面的最后一个扇区之后磁盘继续旋转,在旋转过程中由于磁头还没有准备好读写数据,1号盘面的0号扇区也就是物理地址为8的这个扇区从磁头下面划过的过程中并不能直接把这块的数据读入。如果要读入这块的数据,只能等磁盘再转一圈,让这个扇区再次划过磁头下方。也就是说如果我们把这些盘面相对位置相同的这些扇区都设置为相同的编号,可能会增加延迟时间,为了解决这个问题,可以用错位命名的方式

image-20210505001418631

 

磁盘的管理

image-20210505000121928

 

磁盘初始化

image-20210505001546984

磁盘刚被制造出来时其实是只被划分成了一个个的磁道,扇区的划分在出厂之前低级格式化时进行

之前说的“一个扇区可以存放的数据大小”其实指的是数据区域可以存放的大小

讲文件的物理结构时提到过链式结构,也就是把文件的那些数据块用链接的方式连起来。前一个数据块指向下一个数据块的指针就可以保存在尾部部分,也就是说链接指针并不需要占用数据区域,这样可以方便操作系统管理

Step3:进行逻辑格式化,创建文件系统。包括要创建这些根目录的目录文件

引导块

计算机开机时需要进行一系列初始化的工作,包括初始化CPU,初始化内存,还有初始化像寄存器之类的一些硬件部件。这些初始化工作是通过执行初始化程序(自举程序)完成的

磁盘完成了物理格式化,磁盘分区和逻辑格式化之后,就可以把操作系统的那些相关数据写到磁盘中了,也就是我们所谓的自己安装操作系统的过程

image-20210505001633518

image-20210505001653394

自举装入程序的复杂度不高,很小。所以可以保证自举装入程序不会出错不需要更改

坏块的管理

坏了、无法正常使用的扇区就是“坏块”。这属于硬件故障,操作系统是无法修复的。应该将坏块标记出来,以免错误地使用到它

image-20210505001736103

标记为坏块的这些块之后不再分配给任何一个文件

操作系统在对存储空间进行管理的时候肯定需要读取文件分配表FAT的内容

扇区备用:假如此时操作系统想要使用一个已经坏掉的块,在硬件的层次磁盘控制器硬件部件就会用其中某一个好的备用块来替换这个坏块

 

固态硬盘SSD

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sMyu9IFa-1662216176559)(操作系统.assets/image-20220903170628599.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Cd5puxR-1662216176561)(操作系统.assets/image-20220903170549570.png)]

U盘也使用闪存技术

机械硬盘与固态硬盘

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qNrOPvV7-1662216176562)(操作系统.assets/image-20220903170717551.png)]

固态硬盘的结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WW4WSVHS-1662216176565)(操作系统.assets/image-20220903171038045.png)]

块大小:16KB~512KB

页大小:512B~4KB

系统对SSD的读写以页为单位,一个逻辑块对应一个SSD里面的一个页

如果数据存放在机械硬盘里面,一个逻辑块对应着一个磁盘块/扇区,磁盘的读写以块为单位

 

对于SSD,一个逻辑地址对应的实际物理位置可能会变,闪存翻译层会把映射关系修改正确

想要再次往已经写入数据的页写入数据必须先把一整块擦除,SSD会把同块的其他数据复制到另一块的对应位置,然后再把新数据写到另一块,接着把原来的块擦除,同时闪存翻译层会重新进行映射

理想情况下,固态硬盘的寿命

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yi46ajMF-1662216176566)(操作系统.assets/image-20220903170946050.png)]

  • 13
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值