操作系统第四章——文件管理(下)

文章详细介绍了操作系统中的文件操作,包括创建、删除、打开、读写等,并讨论了文件共享的两种方式(硬链接和软链接)、文件保护措施(口令、加密和访问控制),以及文件系统的层次结构、虚拟文件系统和挂载过程。强调了系统打开文件表在提高文件操作效率中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

江天一色无纤尘,皎皎空中孤月轮


4.1.7 文件的基本操作

知识总览

文件属于抽象数据类型。为了正确地定义文件,需要考虑可以对文件执行的操作。操作系统提供系统调用,它对文件进行创建、写、读、重定位、删除和截断等操作。
请添加图片描述

创建文件

请添加图片描述
在创建一个新文件时,要为新文件目录中为之建立一个目录项,目录项中应记录新文件的文件名以及其在外存中的地址等属性

删除文件

请添加图片描述
在删除文件时,应先从目录中找到要删除文件的目录项,并使之成为空项,然后回收该文件所占用的存储空间

打开文件

当用户对一个文件实施操作时,每次都要从检索目录开始。为了避免多次重复地检索目录,大多数操作系统要求,在文件使用之前通过系统调用open被显式地打开。操作系统维护一个包含所有打开文件信息的表(打开文件表)。所谓“打开”,是指调用open根据文件名搜索目录,将指明文件的属性(包括该文件在外存上的物理位置),从外存复制到内存打开文件表的一个表目中,并将该表目的编号(也称索引)返回给用户。当用户再次向系统发出文件操作请求时,可通过索引在打开文件表中查到文件信息,从而节省再次搜索目录的开销。当文件不再使用时,可利用系统调用close关闭它,操作系统将会从打开文件表中删除这一条目
在多个不同进程可以同时打开文件的操作系统中,通常采用两级表:整个系统表和每个进程表(原因请往下看)。整个系统的打开文件表包含FCB的副本及其他信息。每个进程的打开文件表根据它打开的所有文件,包含指向系统表中适当条目的指针。一旦有进程打开了一个文件,系统表就包含该文件的条目。当另一个进程执行调用open时,只不过是在其进程文件打开表中增加一个条目,并指向系统表的相应条目。通常,系统打开文件表为每个文件关联一个打开计数器(Open Count),以记录多少进程打开了该文件。每个关闭操作 close使count递减,当打开计数器为0时,表示该文件不再被使用,并且可从系统打开文件表中删除相应条目
请添加图片描述
换言之就是“打开”是在用户和指定文件之间建立一个连接,此后用户可有通过该连接直接得到文件信息,从而避免再次通过目录检索文件,当用户再次向系统发出文件操作请求时,系统可以根据用户提供的索引号直接在打开文件表中找出文件信息,这样就节省了大量的检索开销,还显著的提高了对文件的操作速度,若是用户不在需要对该文件实施相应的操作,则可利用“关闭”系统调用来关闭此文件,即断开此连接,而后OS将会把此文件从打开文件表中的表目上删除

注意这里我们再次访问的时候是通过这个编号先来查看内核内存中的进程打开文件表,然后通过进程打开文件表的指向找到系统打开文件表中对应的表项,系统打开文件表中包含这个文件的FCB的副本,所以自然也就能找到FCB,通过FCB就可以找到数据在外存中存放的位置了,注意文件名不必是文件表的一部分,因为一旦完成了对FCB的定位系统就不需要使用文件名

用户打开文件表:进程PCB中保留一个files_struct,称之为用户打开文件表或文件描述符表。表项的序号是文件描述符fd,此登记项内登记系统打开文件表的一个入口指针fp,通过此系统打开文件表项链接到打开文件的活动inode
系统打开文件表:这是为解决多个进程共享文件,父子创建共享文件而设置的系统级的files_struct 可参考这篇文章
当用户打开文件的时候,相关的信息就已经存放于内存中了,
将目录项复制到打开文件表中可以大幅度的提升文件访问的速度的

请添加图片描述
系统的打开文件表记录的是所有的正在被其他进程使用的文件信息,另外进程自己也会有一个打开文件表,在进程的打开文件表中会有一个系统表的索引号,若是另外一个进程b同样的也是打开了这个文件,进程b的系统索引号同样也是指向k,打开计数器是系统的打开文件表中特有的一个字段,有这个总表也是为方便操作,比如方便检查是否可有删除,
不同的进程对文件的访问权限不同,所以访问权限应该在进程的打开文件表中

若是看到这里还不懂可以看看本文的”文件系统在内存中的结构“这一部分可能有所帮助

当然这里的索引号不是整型变量K,更有可能是一个指针变量。

关闭文件

请添加图片描述
关闭文件是回收内存空间,删除文件是回收磁盘空间

读文件

请添加图片描述
这里需要注意进程指明那个文件,指明要写入多少数据,指明数据在内存的存放位置的,注意是进程读文件时根据用户给出的文件名查找目录,从中得到被读文件在外存的地址,在目录项中还有一个指针用于对文件进行读操作,若是已经被打开过了也就意味着系统打开文件表中已经有信息了,所以此时只需要提供一个索引号能到系统打开文件表中找到对应的表项即可

写文件

请添加图片描述
这些参数的填充都是记事本这个程序在背后替我们完成的事情,
在写文件时,根据文件名查找目录,找到指定文件的目录项之后,再利用目录中的写指针进行写操作

知识回顾

请添加图片描述
注意系统打开文件的时候并不是将文件数据直接读入内存,而是将目录项复制到打开文件表中,用户根据返回的索引号查询打开文件表,然后直接操作自己的文件,而不再需要每一次都查询目录,直接查询这个打开文件表便可

4.1.8 文件共享

知识总览

请添加图片描述

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

在树形结构的目录中,当有两个或多个用户要共享一个子目录或文件时,必须将共享文件或子目录链接到两个或多个用户的目录中,才能方便地找到该文件

请添加图片描述
在这种共享方式中,诸如文件的物理地址及其他的文件属性等信息,不再放在目录项中,而放在索引结点中。在文件目录中只设置文件名及指向相应索引结点的指针。在索引结点中还应有一个链接计数count,用于表示链接到本索引结点(即文件)上的用户目录项的数目。当count = 2时,表示有两个用户目录项链接到本文件上,或者说有两个用户共享此文件
就是让不同用户的目录项指向同一个文件的索引结点,并且需要注意不同用户对于文件的命名是可有不同的

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

请添加图片描述
用户三是另外重新建立一个link型文件,这个link文件记录了文件一的存放路径,所以需要多次磁盘IO操作,所以速度较硬链接会慢很多

请添加图片描述

知识回顾

请添加图片描述

4.1.8 文件保护

知识总览

为了防止文件共享可能会导致文件被破坏或未经核准的用户修改文件,文件系统必须控制用户对文件的存取,即解决对文件的读、写、执行的许可问题。为此,必须在文件系统中建立相应的文件保护机制。文件保护通过口令保护、加密保护和访问控制等方式实现。其中,口令和加密是为了防止用户文件被他人存取或窃取,而访问控制则用于控制用户对文件的访问方式
请添加图片描述

口令保护

口令指用户在建立一个文件时提供一个口令,系统为其建立FCB 时附上相应口令,同时告诉允许共享该文件的其他用户。
请添加图片描述

加密保护

请添加图片描述
口令和密码都是防止用户文件被他人存取或窃取,并没有控制用户对文件的访问类型。

访问控制

请添加图片描述
每一个文件都是有一个访问控制表,并且注意这种计算就是分组数乘操作数

知识回顾

请添加图片描述
口令和加密尽管都是需要密码或者说是口令,不过口令中文件并没有加密,而加密保护中需要使用口令对文件进行解密
此外还可以对文件的重命名、复制、编辑等加以控制。这些高层的功能可以通过系统程序调用低层系统调用来实现。保护可以只在低层提供。例如,复制文件可利用一系列的读请求来完成,这样,具有读访问权限的用户同时也就具有了复制和打印权限。
对于多级目录结构而言,不仅需要保护单个文件,而且需要保护子目录内的文件,即需要提供目录保护机制。目录操作与文件操作并不相同,因此需要不同的保护机制。

4.2.1文件系统的层次结构

请添加图片描述
这里的用户接口这一层所作的事情就是在之前提到的文件的基本操作中介绍的,一般用户访问一个文件的时候是先提供一个文件的路径,然后根据这个路径通过文件目录系统找到相应的FCB或索引结点,然后还需要确定此用户是否有对这个文件操作的权限(因为权限表通常都是放在FCB或者索引结点中,所以需要先找到FCB或者索引结点,知道是否有权限之后,若是有权限,打开文件,系统会在系统文件表中创建一个表项,并且返回给用户一个编号或者索引号,用户通过编号或者索引号找系统文件目录表这样下次加快找的速度,然后把这个编号转化为逻辑地址,再将逻辑地址转化为物理地址这就需要物理文件系统,对文件进行操作,此时就需要申请磁盘,就需要设备管理模块,(文件记录号是不是之前提到的系统给用户的编号?应该是的,不过这个编号并不是整形的,而可能是一个指针类型的,下面文章会提到)

知识点回顾

请添加图片描述

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

我们从一个磁盘出厂到物理格式化,再到逻辑格式化,来认识文件系统在外存中是如何一步一步被建立的,首先一个磁盘刚生产的时候是没有划分扇区,所以第一步是低级格式化又叫做物理格式化

物理格式化

请添加图片描述

物理格式话会将磁盘划分成一个个的扇区,物理格式话的时候也会检查是否有坏扇区的存在,若是有则用坏扇区则用备用扇区顶替,并且对于操作系统也是透明的,

逻辑格式化

文件系统存放在磁盘上,多数磁盘划分为一个或多个分区,每个分区中有一个独立的文件系统。文件系统可能包括如下信息:启动存储在那里的操作系统的方式、总的块数、空闲块的数量和位置、目录结构以及各个具体文件等

1)主引导记录(Master Boot Record,MBR),位于磁盘的0号扇区,用来引导计算机,MBR后面是分区表,该表给出每个分区的起始和结束地址。表中的一个分区被标记为活动分区,当计算机启动时,BIOS读入并执行MBR。MBR做的第一件事是确定活动分区,读入它的第一块,即引导块。
2)引导块(boot block),MBR执行引导块中的程序后,该程序负责启动该分区中的操作系统。为统一起见,每个分区都从一个引导块开始,即使它不含有一个可启动的操作系统,也不排除以后会在该分区安装一个操作系统。Windows系统称之为分区引导扇区。除了从引导块开始,磁盘分区的布局是随着文件系统的不同而变化的。文件系统经常包含有如图4.18所列的一些项目。
3)超级块(super block),包含文件系统的所有关键信息,在计算机启动时,或者在该文件系统首次使用时,超级块会被读入内存。超级块中的典型信息包括分区的块的数量、块的大小、空闲块的数量和指针、空闲的FCB 数量和FCB指针等。
4)文件系统中空闲块的信息,可以使用位示图或指针链接的形式给出。后面也许跟的是一组i结点,每个文件对应一个结点,i结点说明了文件的方方面面。接着可能是根目录,它存放文件系统目录树的根部。最后,磁盘的其他部分存放了其他所有的目录和文件。
请添加图片描述
超级块在磁盘的空闲分区管理中学到过,有了超级块就可以找到这个磁盘分区中的所有空闲磁盘块,这样我们新建一个文件给它分配空间就可以从超级块出发,迅速找到空闲块,位示图可以迅速判断某一个特定的磁盘块此时是否是空闲,超级块更多的时候找若干个空闲块,i结点区,所谓i结点也就是我们熟悉的索引结点,每一个文件都有一个与之对应的索引节点,unix中所有的索引结点都是连续的存放于i结点区,可以将这理解为一个超级大的数组,每一个数据元素是一个索引结点,所以我们可以通过一个指定的数组下标迅速的定位我们要找的索引结点,当我们完成逻辑格式化之后根目录也会被建立,因为任何一个文件系统都必须从根目录出发来建立一个新的目录或存储文件,逻辑格式化之后这些灰色的部分就是已经有数据的部分,

文件系统在内存中的结构

请添加图片描述
为了创建新的文件,应用程序调用逻辑文件系统(逻辑文件系统管理目录结构,以便根据给定文件名称为文件组织模块提供所需要的信息。它通过文件控制块来维护文件结构。逻辑文件系统还负责文件保护)。逻辑文件系统知道目录结构的格式,它将为文件分配一个新的FCB。然后,系统将相应的目录读入内存,使用新的文件名和FCB进行更新,并将它写回磁盘。
一旦文件被创建,它就能用于IO。不过,首先要打开文件。系统调用open()将文件名传递给逻辑文件系统。调用open()首先搜索整个系统的打开文件表,以确定这个文件是否已被其他进程使用。如果已被使用,则在单个进程的打开文件表中创建一个条目,让其指向现有整个系统的打开文件表的相应条目。该算法在文件已打开时,能节省大量开销。如果这个文件尚未打开,则根据给定文件名来搜索目录结构。部分目录结构通常缓存在内存中,以加快目录操作。找到文件后,它的FCB会复制到整个系统的打开文件表中。该表不但存储FCB,而且跟踪打开该文件的进程的数量。然后,在单个进程的打开文件表中创建一个条目,并且通过指针将整个系统打开文件表的条目与其他域(如文件当前位置的指针和文件访问模式等)相连。调用 open()返回的是一个指向单个进程的打开文件表中的适当条目的指针。以后,所有文件操作都通过该指针执行。一旦文件被打开,内核就不再使用文件名来访问文件,而使用文件描述符( Windows称之为文件句柄)
当进程关闭一个文件时,就会删除单个进程打开文件表中的相应条目,整个系统的打开文件表的文件打开数量也会递减。当所有打开某个文件的用户都关闭该文件后,任何更新的元数据将复制到磁盘的目录结构中,并且整个系统的打开文件表的对应条目也会被删除。

4.2.3 虚拟文件系统

普通的文件系统

请添加图片描述
我们在写代码的时候若是从一个文件系统打开一个文件的时候,不同的文件系统可能需要的代码有很大的差别,所以操作系统内核应该向上提供一个统一调用的接口,所以在操作系统内部就引入了虚拟文件系统

虚拟文件系统

虚拟文件系统采用了面向对象的思想,它抽象出一个通用的文件系统模型,定义了通用文件系统都支持的接口。新的文件系统只要支持并实现这些接口,即可安装和使用。以Linux中调用write()操作为例,它在 VFS中通过sys_write()函数处理,sys_write()找到具体文件系统,将控制权交给该文件系统,最后由具体文件系统与物理介质交互并写入数据,
请添加图片描述
有了虚拟文件系统之后,用户只需要根据虚拟文件系统制定的标准来写代码就可以了,虚拟操作系统会负责操控底层一个具体的文件系统,但是之前就说过每一个具体系统的参数有区别,所以也就意味着需要虚拟文件系统根据不同的具体的文件系统做出改变,也就意味着需要修改操作系统内核的代码,所以。。。
虚拟文件系统的第二个特点:VFS要求下层的文件系统必须实现某些规定的函数功能(规定函数名,规定函数参数),如:打开/读/写。一个新的文件系统想要在某操作系统上被使用,就必须满足该操作系统VFS的要求
请添加图片描述
但是不同的文件系统的目录项是有很大的差别的,UFS这种系统的每一个目录项只包含文件名和i结点编号,我们需要根据i结点的编号,把这个i结点读入主存,然后才可以知道这个文件的原数据,以及外存的存放位置,
而对于FAT文件系统,只需要读入了某一个文件的目录项,FCB中就包含了我所想知道的关于这个文件的所有信息。
这就造成对于不同的文件系统读入的也是不同的,这也就导致虚拟文件系统需要使用不同的数据结构来表示来自不同的文件系统的信息,

请添加图片描述
所以在虚拟文件系统中,每当我们打开了一个文件之后虚拟文件系统就会给这个文件在主存中新建一个Vnode结点,这个V结点包含的就是各种各样的信息,当我们获得的无论是什么文件系统的目录项,我们都是将其复制到vnode结点中(就相当于把空都给你了,你来填空,填不满也没有关系),这样虚拟文件系统就可以使用一个统一的格式来表示任何文件系统的信息,
注意每一个打开的文件在主存中,都会有一个与之对应的vnode存在于主存中,在使用UFS的文件系统中,我们找到这个文件所对应的目录项之后,会把文件的inode从外存先读入主存,存放于vnode中,所以innde是即存在于外存中,又存在于主存中,

请添加图片描述
不同的文件系统需要实现虚拟文件系统规定的功能,而每一个文件系统具体功能所对应的代码是不同的,所以函数功能指针的作用就是先找到Vnode,然后根据Vnode中的函数功能指针,找到具体的文件系统的的功能函数

文件系统的挂载

请添加图片描述
比如将U盘插入电脑就是一种挂载行为,具体来说就是挂载到虚拟文件系统里面,当我们新挂载一个文件系统需要在挂载表中增加一个表项,每一个文件系统对open,write 都不相同,
所以新挂载的文件系统需要向虚拟文件系统提供一个自己的函数地址列表,也就是上上个图里面那个黄色的东西,这样才能让虚拟文件系统来调用挂载的文件系统所提供的功能函数,

PS:查找的时候,是先查找inode,根据inode来看这个目录所对应的外存块是那些,去找这些块,若是直接找到文件了,通过这个文件所指向的Inode来找外存的磁盘块号,若是找的是下一级的目录,同样的也是通过inode来进行更深一层的深入,
查目录文件的时候按名查不能提前去判断要找的这个文件名属于文件的第几块,所以才需要一块一块的读入,若是找到了这个文件的起始块号之后查找某一个具体的字节通过FAT表就可以了,而不需要一块一块的读入
若是使用UFS查找某一个字节至少需要两次(根目录常驻内存不算,读入Inode所对应的磁盘,根据Inode来找对应的磁盘块又需要一个读磁盘)若是使用FAT找某一个字节,最少找一次便可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值