首页 > 其他分享 >一个操作系统的设计与实现——第14章 文件系统

一个操作系统的设计与实现——第14章 文件系统

时间:2023-11-12 10:13:47浏览次数:34  
标签:文件 操作系统 函数 扇区 文件系统 FCB 硬盘 14

文件系统是操作系统的一个重要模块。本章将要实现的是文件系统。

14.1 什么是文件系统

文件系统是操作系统用于管理硬盘,并使硬盘更易于使用的模块。

想要管理硬盘,就需要记录硬盘扇区的使用情况,可以使用位图实现这个功能。

想要让硬盘更易于使用,就需要一个非常关键的概念:文件。文件可以将底层的起始扇区号、扇区数等信息用一个文件名代替,存储这些信息的数据结构被称为文件控制块(File Control Block,FCB)。使用文件系统时,可以从文件名出发,找到其对应的FCB,并从中取出起始扇区号、扇区数等信息,提供给更底层的函数使用。

文件系统是一个持久化的系统。对文件系统的操作不能仅仅停留在内存中,而是要及时将其写入硬盘。

文件系统并不是一个很复杂的概念,但由于硬盘与CPU之间的效率相差甚远(约5个数量级),所以,工业级的操作系统使用了大量非常复杂的技术以提高文件系统的效率;很多书籍也使用了非常大的篇幅论述文件系统的实现细节。在我们的操作系统中,不考虑文件系统的效率问题。

14.2 文件系统的实现

请看本章代码14/Util.h

第19~20行,声明了两个字符串辅助函数。

接下来,请看本章代码14/Util.hpp

strEq函数相当于C语言标准库的strcmp函数的简化版,其用于判断两个字符串是否相等。

strCopy函数相当于C语言标准库的strncpy函数,其用于复制字符串。

接下来,请看本章代码14/FS.h

第5~10行, 定义了FCB结构体。FCB中需要存放一个文件的起始扇区号和扇区数,一共8字节;然后,需要决定文件名的最大长度。如果将FCB的大小凑整到16字节,那么文件名的最大长度为7(需要扣除字符串结尾的0),笔者认为这个长度过小,于是,将FCB的大小凑整到32字节,这样一来,文件名的最大长度为23。

第13~17行,声明了文件系统的各种函数。

接下来,请看本章代码14/FS.hpp

第9行,定义了长度为16的FCB列表。一个FCB是32字节,所以一个扇区能存放16个FCB。又因为最后一个FCB被用于魔数(见下文),所以我们的操作系统最多支持15个文件。

第10行,定义了硬盘位图的缓冲区,大小为一个扇区。硬盘位图用于管理扇区的使用情况,其存放在硬盘中,这里定义的是其在内存中的读写缓冲区。一个扇区的位图能够管理4096个扇区,共2M。

第11行,定义了硬盘位图。

fsInit函数用于初始化文件系统。文件系统是一个持久化的模块,仅在硬盘上还不存在文件系统时需要初始化一次。所以,需要使用一个魔数来标识硬盘上是否存在文件系统。在工业级的操作系统中,魔数一般定义在超级块(Super Block)中,超级块是文件系统的核心,其中存放的是对于文件系统来说最重要的信息。但我们的操作系统的超级块中只需要存放一个魔数,所以,实现上没有单独构造超级块,而是将FCB列表中的最后一个FCB作废,并在此位置存储魔数。

我们的操作系统使用了硬盘的前100个扇区,所以,文件系统的FCB列表可以存放在第100个扇区;硬盘位图可以存放在第101个扇区;从第102个扇区开始可用于存放文件。

第15行,从硬盘中读取FCB列表。

第17行,验证魔数。

第19~20行,如果魔数验证通过,就说明文件系统已存在,位于第101个扇区的硬盘位图是有效的,可将其读出,然后初始化hdBitmap。请注意,这里的bitmapInit函数不能将位图缓冲区清零,而是应该沿用硬盘中的数据。

第24~30行用于安装文件系统,其只会运行一次。如果读者想要调试这段代码,可以不断修改魔数的取值,或删除虚拟硬盘并重新创建。

第24~25行,清空FCB列表,然后填入魔数。

第27行,初始化硬盘位图。

第29~30行,将FCB列表和硬盘位图分别写入第100,101个扇区,以实现文件系统的持久化。

fsList函数相当于Linux的ls命令。

第37行,遍历15个FCB。

第39行,判断FCB的起始扇区号是否为0。FCB会被初始化为0,而一个文件的起始扇区号不可能为0(至少为102)。所以,如果一个FCB的起始扇区号为0,就说明这个FCB为空。

第41行,如果FCB不为空,就打印这个FCB的文件名,起始扇区号和扇区数。

__allocateFCB函数用于在FCB列表中找到一个空的FCB,并返回其索引值。如果找不到,则返回-1。

fsCreate函数用于创建文件。在我们的操作系统中,创建文件的过程如下:

  1. 在一个很大的起始扇区号(如1000)处写入一个文件
  2. 调用fsCreate函数,将这个文件安装到文件系统中

第63~68行,尝试分配一个FCB索引值。如果分配失败,则退出此函数。

第70~72行,填写FCB的3个数据成员。

第74~80行,将文件复制到文件系统中。

第82~83行,将FCB列表和硬盘位图分别写入第100,101个扇区,以实现文件系统的持久化。

__findFCB函数用于在FCB列表中查找指定的文件名,并返回FCB的索引值。如果找不到,则返回-1。

fsDelete函数用于删除文件。

第103~108行,尝试查找被删除文件的FCB索引值,如果找不到,则退出此函数。

第110行,将此文件从硬盘位图中删除。

第112行,将此文件从FCB列表中删除。

第114~115行,将FCB列表和硬盘位图分别写入第100,101个扇区,以实现文件系统的持久化。

fsLoad函数用于以文件名作为参数加载3特权级任务。

第121行,尝试查找输入文件的FCB。

第125行,如果找到了输入文件的FCB,则从中取出该文件的起始扇区号和扇区数,然后调用loadTaskPL3函数。

接下来,请看本章代码14/Kernel.c

第16行,调用fsInit函数,完成文件系统的初始化。

14.3 测试

本章代码14/Kernel.c用于测试文件系统的四个函数。

标签:文件,操作系统,函数,扇区,文件系统,FCB,硬盘,14
From: https://www.cnblogs.com/yingyulou/p/17825527.html

相关文章

  • 一个操作系统的设计与实现——第16章 键盘驱动(下)
    我们的操作系统虽然已经实现了键盘驱动,但其功能仅限于在屏幕上打印输入的字符,任务并不能读取到这些字符。本章将要实现读取键盘输入的系统调用。16.1读取键盘输入的原理想要让任务读取到键盘输入,最简单的方法是构造一个数组,当键盘中断发生时,将键盘输入的字符保存在这个数组中。......
  • 一个操作系统的设计与实现——第15章 键盘驱动(上)
    到目前为止,我们的操作系统只能输出而不能输入。本章将要实现的是键盘驱动,其能让我们的操作系统接收键盘输入。15.1键盘驱动的原理当按下键盘上的键时,发生了什么呢?原来,每当按下键盘上的键,键盘都会发起至少一次键盘中断;每当一个键弹起时,键盘又会发起至少一次键盘中断;如果一直按住......
  • #2023-2024-1 20231424《计算机基础与程序设计》第7周学习总结
    2023-2024-120231424《计算机基础与程序设计》第7周学习总结作业信息作业属于的课程<班级链接>(2022-2023-1-计算机基础与程序设计)作业要求<作业要求链接>(2022-2023-1计算机基础与程序设计第一周作业)作业目标《计算机科学概论》第8章和《C语言程序设计》第6章......
  • 一个操作系统的设计与实现——第17章 系统交互
    操作系统最终是供用户使用的,所以其需要具备与用户交互的能力,交互方式可以是命令行,图形界面,甚至是触摸屏,语音,实体按钮等。本章将要实现的是系统交互。17.1外壳程序我们的操作系统使用的是基于命令行的交互模式。实现此功能的模块被称为外壳(Shell)程序。事实上,上一章的Test.c已经......
  • 一个操作系统的设计与实现——第3章 保护模式
    实模式下,内存的访问是没有任何限制的,任何程序都能访问和修改任何内存地址,这就导致了实模式下的程序,甚至操作系统自己,都可能自身难保。于是,自8086的下一代产品80286起,保护模式诞生了;进一步的,自80386起,32位保护模式诞生了。3.1内存为什么要分段在学习保护模式之前,需要先讨论一个......
  • 一个操作系统的设计与实现——第2章 主引导记录
    2.1BIOS当按下开机键的那一刻,发生了什么呢?这是一个百废待兴的时刻,所有的硬件设备都刚启动,并没有做好准备,甚至连CPU自己都是。此时,就需要一些外力帮助CPU工作起来。具体来说,在CPU刚启动时,其CS:IP被硬件电路设定为f000:fff0。这个地址并非指向内存,而是指向主板的一个非易失性ROM,......
  • 一个操作系统的设计与实现——第1章 什么是操作系统
    1.1引言什么是操作系统呢?有些读者可能会像曾经的笔者一样,认为操作系统是"一种图形界面";在学习了Linux操作系统后,认为操作系统也可以是"一种命令行"。而不同种类,不同版本的操作系统,则是"不同的图形界面",或是"不同的命令行语法"。那么,以Linux操作系统为例,读者是否想过这些问题呢......
  • 一个操作系统的设计与实现——第5章 加载内核
    一直以来,我们都在使用汇编语言对MBR编程,但对于操作系统这样的复杂程序来说,使用汇编语言是比较困难的。本章将实现操作系统内核的加载与进入。5.1读硬盘的实现原理操作系统存储于硬盘中,现在需要将其读出至内存。想要读硬盘,就需要依次进行以下操作:设定读取的扇区数设定起始扇......
  • 一个操作系统的设计与实现——第9章 硬盘驱动
    操作系统应当具备读写硬盘的能力。因此,本章将要实现的是硬盘驱动。硬盘驱动由两个函数构成:读硬盘函数与写硬盘函数。9.1读硬盘想要读硬盘,就需要提供以下三个信息:起始扇区号读取的扇区数数据存储的地址需要注意的是:读取的扇区数只能是一个8字节的整数。由于读硬盘需要使......
  • 一个操作系统的设计与实现——第8章 内存管理系统
    计算机上的任何程序,包括操作系统自己,都需要使用内存。因此,操作系统需要实现内存管理系统,以进行内存的分配和回收。在我们的操作系统中,内存管理系统由两部分组成:页分配器与页回收器。本章将实现这两个部分。8.1从虚拟地址到物理地址回顾CPU对内存地址的转换过程:使用段寄存器......