FAT12 文件系统

更新时间:2024-03-23 00:04:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

FAT12 文件系统

FAT12文件系统

实验性质:验证+设计 建议学时:2学时

一、实验目的

? ?

了解FAT12文件系统在软盘上的应用。

通过为EOS的FAT12文件系统添加写文件功能,加深对磁盘存储器管理原理的理解。

二、预备知识

2.1 文件系统驱动

阅读《EOS实验指南》第7章的7.4、7.5节,了解文件系统驱动程序的作用——用于将用户对磁盘文件的读写请求转换为对磁盘扇区的读写请求,并负责对磁盘扇区进行管理。 2.2 FAT12文件系统简介

阅读《EOS实验指南》附录B,学习FAT12文件系统技术细节。关于FAT文件系统更详细的信息,可以参阅微软硬件白皮书《FAT: General Overview of On-Disk Format》(在OS Lab的“帮助”菜单中选择“其它帮助文档”中的“FAT文件系统概述”)。

三、实验内容

3.1 准备实验

按照下面的步骤准备实验:

1. 启动OS Lab。

2. 新建一个EOS Kernel项目。

3. 分别使用Debug配置和Release配置生成此项目,从而在该项目文件夹中生成完全

版本的EOS SDK文件夹。 4. 新建一个EOS应用程序项目。

5. 使用在第3步生成的SDK文件夹覆盖EOS应用程序项目文件夹中的SDK文件夹。 3.2 编写代码调用EOS API函数读取文件中的数据

使用OS Lab打开本实验文件夹中的FileApp.c文件(将此文件拖动到OS Lab窗口中释放即可),仔细阅读此文件中的源代码和注释,main函数的流程图可以参见图1。

按照下面的步骤查看EOS应用程序读取文件中数据的执行结果:

1. 使用OS Lab打开在3.1中创建的EOS应用程序项目。

2. 在“项目管理器”窗口中双击Floppy.img文件,使用FloppyImageEditor工具打开

此软盘镜像。 3. 将本实验文件夹中的a.txt文件添加到软盘镜像的根目录中。打开a.txt文件查看其

中的数据。 4. 点击FloppyImageEditor工具栏上的保存按钮,关闭该工具。

5. 使用FileApp.c文件中的源代码替换EOS应用程序项目中的EOSApp.c文件内的源

代码。 6. 按F7生成修改后的EOS应用程序项目。

7. 按F5启动调试。自动运行EOS应用程序EOSApp.exe时,会由于输入的命令行参数

1

FAT12 文件系统

无效而失败。

8. 在EOS控制台中输入命令“A:\\EOSApp.exe A:\\a.txt”后按回车,EOSApp.exe会

读取a.txt文件中的内容并显示在屏幕上,如图2。 9. 结束此次调试。

main函数开始调用CreateFile函数打开要读取的文件否将读取的数据写入文件?是使用标准输出(屏幕)句柄做为输出句柄调用CreateFile函数打开要写入的文件否增加写?是将文件指针移动到文件的末尾使用写入文件句柄做为输出句柄调用ReadFile函数读取文件调用WriteFile函数将读取的数据写入输出句柄否文件读取完毕?是关闭文件main函数结束

图1:main函数流程图

2

FAT12 文件系统

图2:EOS应用程序读取文件中数据的执行结果

FatReadFile函数开始起始读取位置超出文件大小?期望读取字节数超出文件大小?否是重新计算可以读取的字节数从文件的第一个簇开始在簇链表中向后查找偏移位置所在的簇根据偏移位置和要读取的字节数,从簇包含的扇区中读取数据在簇链表中查找下一个要读取的簇否期望的字节数读取完毕?是FatReadFile函数结束

图3:FatReadFile函数流程图

3.3 调试FAT12文件系统的读文件功能

FAT12文件系统的读文件功能是由EOS内核项目fat12.c文件中的FatReadFile函数完成的。按照下面的步骤准备调试该函数:

1. 使用Windows资源管理器打开在3.1中创建的EOS内核项目的项目文件夹,并找到

3

FAT12 文件系统

fat12.c文件。

2. 将fat12.c文件拖动到OS Lab窗口中释放,打开此文件。注意,一定要拖动到3.2

中已经打开EOS应用程序项目的OS Lab中,这样该OS Lab就同时打开了EOS应用程序项目和EOS内核项目中的fat12.c文件,方便后面的调试。

在开始调试之前,仔细阅读fat12.c文件中的FatReadFile函数(第662行)的源代码和注释。提示:

? 函数流程图可以参见图3。

? 参数Vcb指向一个VCB结构体(定义参见io/driver/fat12.h第146行)。VCB结构

体是文件系统设备对象的扩展块,描述了FAT12文件系统的相关信息。例如BPB参

数(BPB结构体定义参见io/driver/fat12.h第57行)、FAT表被读取到内存缓冲区中的位置等。参数Vcb在这里记录了软盘上FAT12文件系统的信息。

? 参数File指向一个FCB结构体(定义参见io/driver/fat12.h第181行)。FCB结

构体是文件控制块,描述了FAT12文件系统中文件的相关信息。例如文件的共享打开属性、文件的第一个簇号、文件大小等。每个磁盘文件在被打开时,文件系统都会为其创建一个FCB结构体。参数File在这里记录了要从中读取数据的文件的信息。

按照下面的步骤调试该函数:

1. 取消注释EOSApp.c文件中的第62行,允许调试该EOS应用程序。 2. 按F7生成。

3. 按F5启动调试。自动运行EOS应用程序EOSApp.exe时,会由于输入的命令行参数

无效而失败。 4. 在EOS控制台中输入命令“A:\\EOSApp.exe A:\\a.txt”后按回车,EOSApp.exe会

读取a.txt文件中的内容。此时OS Lab会弹出一个调试异常对话框,并中断应用程序的执行。

5. 选择“是”调试异常,调试会中断。

6. 在读文件时调用的API函数ReadFile最终会调用FatReadFile函数,所以,在

fat12.c文件的FatReadFile函数开始(第700行)添加一个断点。 7. 按F5继续执行,在断点处中断。

在继续调试FatReadFile函数的执行过程之前,先观察一下该函数的参数都提供了哪些有用的信息。

1. 点击OS Lab工具栏上的“十六进制”按钮,取消其高亮状态,使用十进制查看变

量的值。 2. 选择OS Lab“调试”菜单中的“快速监视”,打开“快速监视”对话框。

3. 在“快速监视”对话框中输入表达式“*Vcb”后按回车。参数Vcb提供的信息如图

4。结合VCB和BPB结构体定义,尝试说明这些信息的含义。 {

?? Bpb = {

BytesPerSector = 512,

SectorsPerCluster = 1 '\\001', ReservedSectors = 1, Fats = 2 '\\002', RootEntries = 224, Sectors = 2880, ??

SectorsPerFat = 9, SectorsPerTrack = 18, Heads = 2,

HiddenSectors = 0, LargeSectors = 0

4

FAT12 文件系统

}, ??

FirstDataSector = 33, NumberOfClusters = 2847 }

图4:参数Vcb提供的信息

4. 在“快速监视”对话框中输入表达式“*File”后按回车。参数File提供的信息如

图5。结合FCB结构体定义,尝试说明这些信息的含义。注意,文件的起始簇号可能不是2。 {

??

FirstCluster = 2, FileSize = 35, ?? }

图5:参数File提供的信息

5. 将鼠标移动到参数Offset上,显示其值为0,说明从文件头开始读取。将鼠标移

动到参数BytesToRead上,显示其值为256,与应用程序中调用ReadFile函数时

输入的缓冲区大小一致。将鼠标移动到参数Buffer上,显示缓冲区所在地址在用户地址空间(小于0x80000000),也就是在应用程序中定义的缓冲区。

接下来,按照下面的步骤调试FatReadFile函数的执行过程: 1. 由于读取文件的起始偏移位置(0)没有超出文件的大小(35),所以按F10单步调

试后,可以继续读取文件。

2. 由于预期读取的字节数(256)大于文件的大小(35),所以实际可读取的字节数(BytesToRead)应为35。按F10直到在第715行中断。

3. 由于要读取的偏移位置Offset是0,所以开始读取的簇Cluster就是文件的第一

个簇。按F10直到在第728行中断。注意,C语言运算符“/”只取商。

4. 第728行计算簇的起始扇区号。按F10单步调试。如果文件第一个簇是2,查看计算的结果FirstSectorOfCluster应该为33,尝试说明计算的方法。 5. 接下来使用两重循环读取扇区中的数据,外层循环是遍历文件簇链中的所有簇,内

层循环是遍历一个簇中的所有扇区。由于该文件大小只有35个字节,都存储在第

一个簇的第一个扇区中,另外,这里使用的FAT12文件系统每个簇只有一个扇区,所以并没有循环执行。按F10单步调试,直到该函数执行完毕,注意观察各个变量的值和计算方法。

6. 按F5继续执行。激活虚拟机窗口查看执行的结果。 7. 结束调试。

为了方便后面的实验,使用Release配置生成该EOS应用程序。 3.4 为FAT12文件系统添加写文件功能 3.4.1 完成一个最简单的情况

由于写文件功能会涉及到为文件分配新的簇、修改文件大小等问题,所以这里首先完成一个最简单的情况:向一个空文件中写入数个字节的数据。

1. 使用OS Lab打开3.1中创建的EOS内核项目。

2. 从“项目管理器”窗口中打开源文件io/driver/fat12.c,目前fat12.c中的函数FatWriteFile(第782行)为空。

3. 将本实验文件夹中的FatAllocateCluster.c文件拖动到OS Lab窗口中打开,将该

文件中FatAllocateCluster函数复制到fat12.c文件中FatWriteFile函数的前

5

FAT12 文件系统

面。在FatWriteFile函数中需要调用FatAllocateCluster函数来获得一个空闲簇。 4. 将本实验文件夹中的FatWriteFile.c文件拖动到OS Lab窗口中打开,使用该文件中FatWriteFile函数的函数体替换fat12.c文件中FatWriteFile函数的函数体。 5. 在“项目管理器”窗口中双击Floppy.img文件,使用FloppyImageEditor工具打开

此软盘镜像。 6. 打开EOS应用程序项目文件夹,将Release文件夹中的EOSApp.exe(没有调试信

息)添加到软盘镜像中。 7. 将本实验文件夹中的a.txt、b.txt、c.txt和d.txt文件添加到软盘镜像中。 8. 点击FloppyImageEditor工具栏上的保存按钮,关闭该工具。 9. 按F7生成修改后的EOS内核项目。注意,要使用Debug配置。 10. 按F5启动调试。

在EOS控制台中分别执行下面三组命令,查看写文件的结果: ? 输出a.txt文件内容:

A:\\EOSApp.exe A:\\a.txt

输出b.txt文件内容(无内容): A:\\EOSApp.exe A:\\b.txt

将a.txt文件内容写入b.txt文件: A:\\EOSApp.exe A:\\a.txt A:\\b.txt 输出b.txt文件内容: A:\\EOSApp.exe A:\\b.txt ? 输出d.txt文件内容:

A:\\EOSApp.exe A:\\d.txt

将d.txt文件内容写入b.txt文件: A:\\EOSApp.exe A:\\d.txt A:\\b.txt 输出b.txt文件内容: A:\\EOSApp.exe A:\\b.txt ? 输出c.txt文件内容:

A:\\EOSApp.exe A:\\c.txt

将c.txt文件内容写入b.txt文件: A:\\EOSApp.exe A:\\c.txt A:\\b.txt 输出b.txt文件内容: A:\\EOSApp.exe A:\\b.txt

可以使用本实验文件夹中的b.txt重新覆盖Floppy.img文件中的b.txt文件后,在FatWriteFile函数的第一行语句处添加一个断点,单步调试上面的三个写文件的命令,帮助理解FatWriteFile函数中各行语句的意义。

3.4.2 使FatWriteFile函数可处理跨越扇区边界的写入数据

要求

在3.4.1中调试FatWriteFile函数时可以发现,每次写入的数据(最多256字节)都是从扇区头开始,或者在扇区末结束,从未发生过跨越扇区边界的情况,所以FatWriteFile函数的代码也就没有处理这种情况。现在要求修改FatWriteFile函数,使该函数能够处理写入的数据跨越扇区边界的情况。 测试方法

在b.txt文件大小为0的情况下,可以执行下面的一组命令:

6

FAT12 文件系统

? 输出c.txt文件内容:

A:\\EOSApp.exe A:\\c.txt

输出b.txt文件内容(应无内容): A:\\EOSApp.exe A:\\b.txt

将c.txt文件内容写入b.txt文件(本次写数据不会跨越扇区边界): A:\\EOSApp.exe A:\\c.txt A:\\b.txt

输出b.txt文件内容(应为一份c.txt文件的内容):

A:\\EOSApp.exe A:\\b.txt

将c.txt文件内容增加写入b.txt文件(本次写数据会跨越扇区边界): A:\\EOSApp.exe A:\\c.txt A:\\b.txt -a

输出b.txt文件内容(应为两份c.txt文件的内容): A:\\EOSApp.exe A:\\b.txt

提示

由于IopReadWriteSector函数(定义参见io/block.c第91行)只能对整个扇区进行读写操作,不能跨越扇区边界,所以只能通过修改FatWriteFile函数来解决该问题。

由于目前EOS应用程序中定义的缓冲区大小是256字节,所以调用函数FatWriteFile写入的数据最多也是256字节,这就意味着写入的数据只可能跨越一个扇区的边界。所以,可以尝试根据起始写入的位置和写入数据的大小将要写入的数据分割为不跨越扇区边界的两块数据,对分割后的两块数据分别处理:

?

对于要写入当前扇区内的数据,可以直接调用IopReadWriteSector函数并设置合适的参数来执行写扇区操作。如果整个数据不跨越扇区边界,当然就都写入当前扇区即可。

对于要写入下一个扇区内的数据,必须调用FatGetFatEntryValue函数根据当前簇号得到下一个簇号,如果得到的下一个簇号大于0xFF8,还需要调用FatAllocateCluster函数分配一个新簇,并调用FatSetFatEntryValue函数将新簇链接到当前簇的后面。待下一个簇准备好后,可以根据下一个簇号计算出其对应的扇区号,然后就可以调用IopReadWriteSector函数并设置合适的参数来执行写

扇区操作。

调用IopReadWriteSector函数时使用的参数一定要设置正确,特别是扇区号、扇区内起始位置、写入数据缓冲区地址和写入的字节数目,在跨越扇区边界时这些参数都会有变化。尽量不要修改FatWriteFile函数的参数和已经定义的局部变量,如果需要,可以定义新的局部变量。

如果编写的代码有问题,在测试时可能会破坏软盘上的文件或文件系统,此时可以选择OS Lab“工具”菜单中的“FloppyImageEditor”打开FloppyImageEditor工具,点击工具栏上的“保存”按钮,保存一个空白的Floppy.img文件,并覆盖到EOS内核项目文件夹中。 3.4.3使FatWriteFile函数可处理跨越多个扇区边界的写入数据 要求

在3.4.2中完成的FatWriteFile函数只能处理写入的数据跨越一个扇区边界的情况,当写入的数据大小为1024字节(或更大)时,显然就不能处理了。现在要求继续修改FatWriteFile函数,使该函数能够处理写入的数据跨越多个扇区边界的情况。

在开始修改代码之前,将EOS应用程序使用的缓冲区大小BUFFER_SIZE修改为1024字节,使用Release配置重新生成EOSApp.exe,并将该可执行文件放入EOS内核项目的软盘镜像中。 测试方法

?

7

FAT12 文件系统

与3.4.2中的测试方法相同。可以使用更大的c.txt文件执行多次增加写命令来进行测试。 提示

?

必须使用循环来处理写入数据跨越多个扇区边界的问题。每次循环时只将合适的数据写入当前簇,在后面的循环中将余下的数据写入簇链中后面的簇,直到所有数据写入完毕。

每次向簇中写数据之前都需要判断是否需要分配新簇。

前一个簇号和当前簇号这两个变量对于管理簇链非常重要,在循环的过程中要注意维护好这两个变量的值,保证在每次循环时这两个变量都保存了正确的簇号。 调用IopReadWriteSector函数时使用的参数一定要设置正确,特别是扇区号、扇区内起始位置、写入数据缓冲区地址和写入的字节数目。

当前FAT12文件系统中一个簇只包含一个扇区,为了简化程序,可以不考虑一个簇中包含多个扇区的情况。

在函数结束前,注意要修改文件大小并返回实际写入的字节数量。

? ? ? ? ?

四、思考与练习

? ? ?

结合FAT12文件系统,说明“文件大小”和“文件占用磁盘空间大小”的区别,并举例说明文件的这两个属性值变化的方式有什么不同。

EOS应用程序在读写文件时,缓冲区大小设置为512的倍数比较合适,说明原因。 为FatWriteFile函数添加适当的错误处理功能,提高EOS文件系统的可靠性。例如在调用FatAllocateCluster函数分配新簇时,可能由于没有可用的磁盘空间而返回失败,为这种情况添加错误处理功能,并设计一种方案测试你编写的代码。如果你成功处理了这种情况,注意观察一下你在处理这种错误时,是否能够保证文件大小与写入的数据保持同步,如果出现了不同步的情况,考虑解决的办法。

修改FatWriteFile函数,使该函数能够处理一个簇包含多个扇区的情况。一个簇包含扇区的数量可以由Vcb->Bpb.SectorsPerCluster获得。 分析使用链式分配方式管理磁盘空间的优缺点。

? ?

8

本文来源:https://www.bwwdw.com/article/q4r8.html

Top