Status
Done
实验目的
- Nachos系统原有的文件系统只支持单级索引,最大能存取30 * 128 = 3840字节大小的文件。本实验将在理解原文件系统的组织结构基础上扩展原有的文件系统,在Lab4的基础上,设计并实现具有二级索引的文件系统。
- 为Nachos增加命令行选项-DI。执行./nachos -DI时显示Nachos磁盘的以下信息:Nachos磁盘的总体大小,已使用空间大小,空闲空间大小,普通文件数目,全部普通文件的总字节数,全部普通文件占用的空间大小(不包括文件头占用的,但加上普通文件数据扇区的内碎片),总内碎片字节数(仅计普通文件数据扇区造成的)。
- 若要求为Nachos文件增加rwx权限(可读,可写,可执行),请给出在Nachos中实现的具体方法(不要求实现可运行的代码。在实验报告中用文字描述即可,必要时可在文字中结合关键代码片段、数据结构、对象等说明)。
二级索引文件头i-node设计:
上图中,在扇区长度为128字节,int长度为4字节,均为Nahcos在X86平台上的默认值。构建具有二级索引的i-node,文件头原先的2-30项还是直接索引,最后的第31项指向二级索引块,这个二级索引块存放新的索引条目,有32项(数组下标为0~31)。
实现二级索引后的文件最大长度为:(29 + 32)* 128 = 7808字节。
二级索引块是动态产生的,当文件大小不需要它时,一级索引块的最后一项可设置为-1,此时不存在二级索引块。当文件大小增长到一级索引无法支持时,再分配一个新的块存二级索引,并将二级索引块的扇区号存入一级索引块的第31项。
参阅:
code/lab5/n5
code/lab5/n5readme.txt
code/lab5/n5screen.txt
注1:若Lab5全部完成,演示提交的代码为带有-DI命令行选项的。
实验步骤与内容
实现具有二级索引的文件系统
Nachos原有的文件头为文件扇区号预留了30个位置,为了扩展文件头可以表示的扇区号个数,可以将最后一个位置作为指向另一个扇区的指针,前29个扇区号存储在一级索引,另外32个扇区号存储在二级索引。
重新定义dataSectors后,需要重写新建、拓展、打印和获取扇区号的函数。为了方便修改代码,增强可读性,选择在filehdr.h中修改、添加了一些宏。umDirect2表示二级索引能保存的扇区数量32,NextPtrIndex是一级索引中指向二级索引扇区的索引号,便于查找二级索引、判断是否存在二级索引。
由于增加了二级索引,需要对Allocate函数进行修改;
NumDirect - 1 + NumDirect2
计算修改后的文件系统最多可以支持的扇区数,如果空闲扇区数目不足以分配给这个文件,那么直接返回FALSE
,表示分配失败;如果numSectors
小于或等于NextPtrIndex
,说明文件所需扇区可以完全由直接索引来满足,于是使用freeMap->Find()
在空闲bitmap中查找第一个可用的扇区,返回它的编号,并将其分配给该文件的直接索引,同时将dataSectors[NextPtrIndex] = -1
表示这里没有使用二级索引。如果
numSectors > NextPtrIndex
,说明需要二级索引来补充;- 直接索引部分通过
freeMap->Find()
来为所有NextPtrIndex
个指针分配相应的扇区。
- 然后为二级索引表本身分配一个扇区,这个扇区地址存储在
dataSectors[NextPtrIndex]
中,用于后续间接寻址。
- 最后将二级索引写入硬盘
接下来需要修改Deallocate函数,如果文件没有二级索引,则执行的释放过程与之前相同;若文件存在二级索引,还需要将二级索引进行删除,首先读取二级索引表,删除二级索引扇区,然后删除二级索引列表中指向的扇区,需要删除的个数为
numSectors – NextPtrIndex
,删除扇区前同样需要先检查扇区是否被使用。同时修改根据字节偏移计算对应扇区号的函数ByteToSector,使其符合二级索引的特点。如果扇区索引在二级索引的指针前,则返回对应一级索引号,否则读取二级索引表,获得对应扇区号。
而输出文件内容时,也需要考虑到二级索引的影响,于是对Print函数进行修改,当然,该函数在只有一级索引的情况下,与之前的处理方法并无二样;而在处理含二级索引的文件时,需要首先输出一级索引的扇区号,然后输出二级索引的扇区号;接下来输出File Content部分,一次输出一级索引和二级索引对应的文件内容,一级索引循环至二级索引指针NextPtrIndex,而二级索引的文件内容需要输出numSectors – NextPtrIndex个。
此处只展示新增的二级索引输出内容
实验四添加的文件扩展函数Extend也需要进行修改,由于现有扇区数随着二级索引的添加而增多,所以判断需要的扇区数是否超过了现有扇区数的内容需要进行修改;若扩展后仍是一级索引,则代码不需要变动;若需要扩展至二级索引大小,需要分情况讨论。
- 当前文件不存在二级索引,先将一级索引表填充完毕,然后创建二级索引表,为剩余内容分配二级索引,具体行为与Allocate函数相似;
- 当前文件存在二级索引,读取其二级索引表,在其基础上添加新的扇区即可
测试
- 将huge文件拷贝进nachos文件系统
- 列出所有文件
可以看到huge文件已经拷贝成功,但是大小并没有超出一级索引的容量,接下来在源文件后继续插入一个huge文件;
- 列出所有文件
可以看到File Blocks中不仅输出了一级索引扇区号6~34,还输出了二级索引扇区号36~44,后方的文本也是连续的,说明Extend函数工作正常。
为Nachos增加命令行选项-DI
先对需要输出的数据内容进行分析,观察n5screen文件的输出格式
在filesys文件中添加PrintInfo函数,完成前三项数据的输出,先创建一个
BitMap
对象,用来管理磁盘扇区的空闲与使用情况;再创建一个 Directory
对象,便于后续对文件数据的获取,NumDirEntries
是目录可以容纳的最大文件条目数。freeMap和directory的文件在文件系统初始化后保存在成员变量中,利用FetchFrom即可载入两个文件。磁盘大小可由NumSectors * SectorSize计算得来,其中
NumSectors
是磁盘上的总扇区数。SectorSize
是每个扇区的大小(字节)已使用空间大小可由BitMap进行统计,
BitMap
中包含了所有扇区的使用信息,其中每个扇区是否被占用可以通过 Test(int index)
函数来查看。空闲空间大小可以通过空闲位图freeMap来统计空闲扇区的数量。
调用Directory类的PrintInfo函数,输出文件数据,最后释放freeMap和directory俩对象的空间
Directory类中的PrintInfo函数分析如下,利用for循环遍历所有文件头的大小信息,
tableSize
代表了目录表中可存储的文件或目录条目的数量。若目录表中当前条目被使用了,说明该位置保存的是有效的文件或子目录信息。可以通过
hdr->FetchFrom(table[i].sector)
从磁盘中获取该文件的文件头,并将文件数目加一;拿到了文件头,可以通过FileLength()
函数获取文件的字节长度,表示该文件实际占用的数据大小,将其累加即可得到全部文件的总字节数;通过文件的字节长度可以计算出该文件占用的完整扇区数量,累加即可获得普通文件占用的完整扇区数,将其乘以扇区大小即可获得普通文件占用的空间大小;通过文件字节数是否与扇区大小整除来判断该文件是否存在内碎片。总的内碎片大小为总占用扇区字节数减去总文件字节数。
由于题目要求新增命令行选项,需要在main.cc文件中加入条件分支
测试
- 运行命令,输出文件系统信息
可以看到,扇区位图和文件内容总共占据了45个扇区,没有内碎片
- 插入不足扇区大小倍数的文件
拷贝后,扇区增加了两块,内碎片多了90字节
- 继续拷贝文件进行测试
- 测试删除文件
文件系统恢复原状
为Nachos文件增加rwx权限
在目前的Nachos文件系统中,没有用户分类的概念,也就没有同组用户和其它用户的概念。一个线程打开文件以后,就获得了对该文件操作所有的权利
大多数实用文件系统都提供对文件存取进行保护的功能,保护的一般方法是将用户分类、以及对不同类的用户规定不同的存取权。
同时因为现在我们的nachos仍然没有用户分类,所以在标记文件权限时,不用考虑用户带来的差异。
权限分为:读,写,可执行。
首先修改文件头结构,在FileHeader中,增加一个用于表示权限的字段,考虑到文件字节数最大为7808,没有超过short int的范围,可以在文件头中,将numBytes的类型改为short,然后添加一个short类型的权限信息modeBits。其中每个字符对应一位权限,1表示有权限,0表示无权限。
如7(111)表示可读可写可执行、6(110)表示可读可写不可执行、4(100)表示只可读。
在文件系统中执行读、写、执行操作之前,需要添加权限检查的逻辑。这可以通过增加对 modeBits 字段的检查来实现。
在openfile访问文件时,需要调用openfile中hdr,先去判断用户是否有对应操作权限,如果没有,raiseException抛出权限异常。
为了方便文件权限的修改,可以在文件头增加一个chmod函数。
结论分析和体会
本次实验对Nachos的文件索引存储结构进行了探索,开辟额外的扇区,实现了文件的二级索引存储,并能够在文件删除时完整删除申请的空间。在尝试输出文件系统信息的实验中,探索了内碎片的计算方式。经过本实验,我加深了对操作系统文件系统的理解。