山东大学软件学院操作系统课程设计Nachos-实验四-基本文件系统扩展

说明:blog 中写到的这几个实验,不全面而且也不是上交实验报告的最终版本(是自己实验过程中用typora简单记录的笔记),完整内容(含代码+实验报告)可以通过(山东大学软件学院操作系统课设)下载,或者关注“陌兮blog”免费获取
在这里插入图片描述

一、文件系统分析

查看 /filesys/filesys.cc 中文件系统的构造函数,可以发现以下信息

#define FreeMapSector 		0
#define DirectorySector 	1
#define FreeMapFileSize 	(NumSectors / BitsInByte)
#define NumDirEntries 		10
#define DirectoryFileSize 	(sizeof(DirectoryEntry) * NumDirEntries)

FileSystem::FileSystem(bool format)
{ 
    if (format) {   // 是否应该初始化磁盘
      BitMap *freeMap = new BitMap(NumSectors); // 创建文件位图
      Directory *directory = new Directory(NumDirEntries); // 创建包含10个文件目录项的文件目录表
      FileHeader *mapHdr = new FileHeader; // 创建文件位图的文件头
      FileHeader *dirHdr = new FileHeader; // 创建文件目录表的文件头
      
      // 第一步:文件位图中标记0、1号扇区被占用
      freeMap->Mark(FreeMapSector);		// 0号扇区为文件位图文件头
      freeMap->Mark(DirectorySector); // 1号扇区为文件目录表文件头

			// 第二步:在文件系统中分配位图文件与文件目录表的空间(传入文件位图与空间大小)
      ASSERT(mapHdr->Allocate(freeMap, FreeMapFileSize));   // 位图文件大小为128字节,1个扇区
      ASSERT(dirHdr->Allocate(freeMap, DirectoryFileSize)); // 十个文件目录项大小

			// 第三步:将更新后的位图文件头、文件目录表文件头写入磁盘
      mapHdr->WriteBack(FreeMapSector);   // 传入对应文件头所在扇区号
      dirHdr->WriteBack(DirectorySector);

      // 第四步:创建位图文件、文件目录表的Openfile, Openfile中存储文件头与文件读写位置
      freeMapFile = new OpenFile(FreeMapSector);			// 传入文件头所在扇区, 用于创建Openfile文件头
      directoryFile = new OpenFile(DirectorySector);	// 文件读写位置初始为0
     
			// 第五步:将位图文件信息、文件目录项信息传入对应Openfile中
      freeMap->WriteBack(freeMapFile);	 // 确定Openfile的起始扇区与结束扇区,开辟文件缓冲区
      directory->WriteBack(directoryFile); // 初始化整个文件
    } else {
      // 非初始化操作,则根据原有位图文件头、文件目录表文件头信息初始化Openfile
      freeMapFile = new OpenFile(FreeMapSector);
      directoryFile = new OpenFile(DirectorySector);
    }
}

其中主要包含了位图文件、文件目录表的文件头、Openfile的创建,并将初始化信息写入磁盘。其中位图文件用每位的0、1来表示磁盘该位置是否空闲,分配时从前开始找,一旦有空位则直接分配。另外,从上面文件系统创建的部分可以发现,当文件创建后其大小则无法改变

我们接下来需要自行实现的两个文件命令,-ap、-hap

nachos [-d f] -ap UNIX_filename nachos_filename:表示将一个 UNIX 文件内容添加到 nachos 文件的末尾。
nachos [-d f] -hap UNIX_filename nachos_filename:表示将一个 UNIX 文件内容从 nachos 文件的中间部分开始向后添加并覆盖 nachos 文件的后半部分。

二、文件系统扩展

1、老版本

nachos -ap 与 -hap 命令的实现

首先观察一下 main.cc 中是如何实现 nachos -ap 命令的

else if (!strcmp(*argv, "-ap")) {  // append from UNIX to Nachos
    ASSERT(argc > 2);
    Append(*(argv + 1), *(argv + 2), 0);
    argCount = 3;
}

可以发现 “-ap” 的命令调用了函数 Append(),而该函数主要调用的是 OpenFile::Write()

OpenFile::Write(char *into, int numBytes)
{
   int result = WriteAt(into, numBytes, seekPosition);
   seekPosition += result;
   return result;
}

OpenFile::Write() 调用的是 OpenFile::WriteAt(),因此我们接下来考虑如何修改 OpenFile::WriteAt() 函数来实现该功能。

对原有 WriteAt 函数的分析可以看到,原有函数并不支持写入的数据超过其文件原有大小,因此我们现在需要修改该函数。

// 检查输入是否合法以及避免输入数据超过文件大小
if ((numBytes <= 0) || (position >= fileLength))  // For original Nachos file system
    //if ((numBytes <= 0) || (position > fileLength))  // For lab4 ...
    return 0;				
// check request
if ((position + numBytes) > fileLength)
    numBytes = fileLength - position;

接下来实现这两个命令

大概的思路就是要修改 WriteAt 方法,如果说写入的数据超出了文件的大小,那么进行扩展,再申请新的内存空间。然后调用 OpenFile 的 WriteBack 函数写回磁盘,这个函数通过调用 filehdr 的 WriteBack 方法实现数据的写回操作,我们需要将修改后的文件头写回硬盘时,需要获取该文件头所在扇区号,因此我们在 OpenFile 类中增加一个 sector 变量用于记录该文件头所在扇区号。

首先来实现 ExtendSpace 函数,修改文件大小的方法,完成对文件的扩展,并能够根据文件大小为其分配足够大的扇区。

首先在文件 fileheader.h 中类定义中添加了方法 bool ExtendSpace(int newSize); 然后在文件 fileheader.cc 中实现 FileHeader::ExtendSpace 方法

实现思路:首先根据数据大小判断是否需要扩展数据扇区,这里有两种情况,若不需要,就简单地修改文件大小,若需要,就分配扇区,然后再修改大小。

bool
FileHeader::Extend(int newSize)
{
    if(newSize<numBytes)return FALSE;   //if not a extend operation
    if(newSize==numBytes)return TRUE;   //if size not change
	//计算所需的空间
    int newNumSectors  = divRoundUp(newSize, SectorSize);   //the number of sectors the new size need to be allocated.
    //如果所需空间等于numSectors(原有的空间)
    if(newNumSectors == numSectors){
        //设置一下大小
        numBytes = newSize; 
        return TRUE; 
    }
	//否则计算一下还需要申请的空间
    int diffSector = newNumSectors - numSectors;    
	
    OpenFile *bitmapfile = new OpenFile(0);
    BitMap *freeMap;//新建一个位图
    freeMap = new BitMap(NumSectors);
    freeMap->FetchFrom(bitmapfile);//从磁盘中取出位图
	printf("debug in fhdr extend where new Sector=%d \n",freeMap->NumClear());
    //if disk is full or file size is too big.
    if(newNumSectors>NumDirect||freeMap->NumClear()< diffSector)return FALSE;   
	//申请新的空间,并且存储到文件头
    int i;
    //i从numSectors到newNumSectors,即循环diffSector次
    for(i = numSectors; i<newNumSectors; i++)
    {
        dataSectors[i] = freeMap->Find();
    }
    numBytes = newSize;
    numSectors = newNumSectors;

    return TRUE;
}

接下来实现 WriteBack() 方法:

在文件 openfile.h 类定义中添加方法声明 void WriteBack(); ,然后添加属性 int sector; ,用于记录该文件头所在扇区号

class OpenFile {
  public:
 
//2021.11.21add+++++++++++++++++++++++++++++++++++
	void WriteBack();
//2021.11.21add+++++++++++++++++++++++++++++++++++
private:
  
//2021.11.21add++++++++++++++++++++++++++++++++
	int sector;
//2021.11.21add++++++++++++++++++++++++++++++++

在文件 openfile.cc 构造方法中添加 this->ector = sector; 。

OpenFile::OpenFile(int sector)
{ 
//2021.11.21add++++++++++++++++++++++++++++++++++++++++
	this->sector = sector;
//2021.11.21add++++++++++++++++++++++++++++++++++++++++

WriteAt 方法中修改对于 (position + numBytes) > fileLength 的处理

//2021.11.21add++++++++++++++++++++++++++++++++++++++++
//    if ((numBytes <= 0) || (position >= fileLength))  // For original Nachos file system
    if ((numBytes <= 0) || (position > fileLength))  // For lab4 ...
		return 0;	

	// check request
    if ((position + numBytes) > fileLength)
		//numBytes = fileLength - position;
		hdr->ExtendSpace(position+numBytes);
//2021.11.21add++++++++++++++++++++++++++++++++++++++++	

实现方法 OpenFile::WriteBack ,通过调用 filehdr 的 WriteBack 方法实现数据的写回操作

void
OpenFile::WriteBack()
{
    hdr->WriteBack(sector);
}

最后一步就是按照实验指导书上所提及的,去除掉fstest.cc 中 Append 方法的 openfile->WriteBack() 前面的注释。

//2021.11.21add++++++++++++++++++++++++++++++++++++++++
//  Write the inode back to the disk, because we have changed it
  openFile->WriteBack();
  printf("inodes have been written back\n");
//2021.11.21add++++++++++++++++++++++++++++++++++++++++

2、验收版本

首先需要实现openFile类的WriteBack方法,添加成员变量hdrSector用于记录该文件头所在扇区号,并按照实验指导书上所提及的,去除掉fstest.cc 中 Append 方法的 openfile->WriteBack() 前面的注释。

在openfile.h文件中的openFile类里面添加WriteBack方法

//lab4 add++++++++++++++++++++++++++++
void WriteBack();

添加私有成员变量hdrSector

private:
	//lab4 add+++++++++++++++++++++++++++++
	int hdrSector;

然后在openfile.cc 中实现WriteBack方法

//lab4 add++++++++++++++++++++++++++++
void
OpenFile::WriteBack()
{
    hdr->WriteBack(hdrSector);
}

在openfile.cc文件中的openFile类构造方法中初始化成员变量hdrSector

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BhJ6VjBD-1642243978465)(实验报告.assets/image-20211211200655906.png)]

去除掉fstest.cc 中 Append 方法的 openfile->WriteBack() 前面的注释。

//lab4 add++++++++++++++++++++++++++++
// Write the inode back to the disk, because we have changed it
openFile->WriteBack();
printf("inodes have been written back\n");

接下来实现文件扩展方法ExtendSpace

在filehdr.h文件中的FileHeader类里面添加ExtendSpace方法

//lab4 add++++++++++++++++++++++++++++  
bool ExtendSpace(OpenFile *bitmapfile,int newSize);

然后在filehdr.cc文件实现ExtendSpace方法

//lab4 add++++++++++++++++++++++++++++
bool
FileHeader::ExtendSpace(OpenFile *bitmapfile,int newSize)
{
	//计算所需扇区
    int newNumSectors  = divRoundUp(newSize, SectorSize);
	//不需扩展,直接更新文件头信息
    if(newNumSectors == numSectors){
        numBytes = newSize; 
        return true;   
    }
	//需要扩充的扇区数量
    int diffSector = newNumSectors - numSectors;    
	
    BitMap *freeMap = new BitMap(NumSectors);
    freeMap->FetchFrom(bitmapfile);
	
	//超出一级索引||空间不足
    if(newNumSectors>NumDirect||freeMap->NumClear()< diffSector){
		return false;   
    }
	//分配新扇区,并更改文件头信息
    for(int i = numSectors; i<newNumSectors; i++)
    {
        dataSectors[i] = freeMap->Find();
    }
    numBytes = newSize;
    numSectors = newNumSectors;
    return true;
}
//lab4 add+++++++++++++++++++++++++++++++++++++++++

最后修改openfile.cc文件中的openFile类的WriteAt函数,判断文件是否需要扩展,如果需要扩展则调用ExtendSpace方法进行文件扩展

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RD72jYZx-1642243978466)(实验报告.assets/image-20211211200428889.png)]

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
3.4 独立实验 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 设有两个并发执行的父子进程,不断循环输出各自号、优先数和调度策略。 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 进程初始调度策略均为系统默认和优先级。当 父进程收到 进程收到 由键盘 由键盘 Ctrl+CCtrl+C Ctrl+C 发 出的 SIGINT SIGINTSIGINTSIGINTSIGINT信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 信号时会自动将其优先数加 1,子进程 子进程 收到 由键盘 由键盘 Ctrl+ZCtrl+Z Ctrl+Z发出的 SIG SIGTSTP STP信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 信号时会自动将其优先数减 1。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。 请编程实现以上功能。
### 回答1: 操作系统课设实验七是关于nachos内存地址扩展实验。在操作系统中,内存地址扩展是为了解决内存空间不足的问题,能够扩大可用的内存地址范围。 在这个实验中,我们需要实现内存地址扩展的功能。首先,我们需要修改内核代码,以支持更大的内存空间。这包括对页表、内存管理和地址映射等方面的修改。 接下来,我们需要修改操作系统的编译选项,以允许nachos使用扩展后的内存地址。这可能涉及到修改编译器、链接器和加载器等工具链的配置。 然后,我们需要运行一系列的测试用例来验证内存地址扩展的功能。这些测试用例涵盖了不同的场景,包括进程的创建与销毁、内存的分配与释放、页表的更新等。通过这些测试用例的运行,我们可以验证内存地址扩展是否成功地被实现。 最后,我们还需要撰写一份实验报告,详细描述我们在实验中遇到的问题、解决的方法以及实验结果。这份报告应包括实验设计、实验步骤、结果分析和总结等内容。 总的来说,实验七的目标是通过对nachos内核代码的修改和配置,实现内存地址的扩展功能,并验证其正确性和可行性。通过这个实验,我们可以更深入地理解操作系统的内存管理机制,并且加深对nachos操作系统的理解和熟悉程度。 ### 回答2: 在操作系统课设实验七中,我们将学习如何扩展Nachos操作系统中的内存地址空间。 内存地址扩展是指增加系统能够使用的内存地址范围。在Nachos操作系统中,默认的内存地址范围是32位,即可以寻址的内存大小为2^32个字节。然而,随着计算机系统的发展和应用的需求增加,这样的内存地址范围已经不足以满足现代计算机系统的要求。 在扩展内存地址空间之前,首先需要了解操作系统是如何管理内存的。在Nachos中,操作系统使用页表来实现虚拟内存的管理。每个进程都有自己的页表,其中记录了虚拟页面和物理页面之间的映射关系。操作系统通过访问页表来确定虚拟地址对应的物理地址。 实现内存地址扩展需要进行以下几个步骤: 1. 修改页表的结构:为了支持更大的内存地址范围,我们需要修改页表的数据结构。可以考虑使用更长的物理地址字段或者增加页表的层次结构来扩展内存地址范围。 2. 修改地址翻译机制:修改地址翻译机制,使其支持新的页表结构。这涉及到对地址翻译机制的修改和扩展,确保能够正确地将虚拟地址转换为物理地址。 3. 修改内存管理:修改内存管理模块,以支持更大的内存地址范围。这可能涉及到对缺页异常处理、页面替换算法和内存分配算法等方面的修改。 4. 修改其他相关模块:可能还需要修改其他相关模块,以适应新的内存地址扩展。 通过以上步骤的修改,我们可以成功地扩展Nachos操作系统的内存地址空间。这样做可以提高系统的性能和资源管理能力,更好地满足现代计算机系统的需求。 ### 回答3: 操作系统课设实验七是关于Nachos内存地址扩展的。在实验中,我们需要扩展Nachos操作系统的内存地址空间。 首先,为了理解内存地址扩展的必要性,我们需要了解Nachos操作系统的内存地址限制。在默认情况下,Nachos操作系统的内存地址空间是有限的,这意味着我们只能使用有限的内存来运行程序。然而,在实际应用中,我们经常需要处理更大规模的问题,这就需要更大的内存空间来存储和运行程序。 为了扩展内存地址,我们可以采用虚拟内存的方法。虚拟内存是一种计算机系统的内存管理技术,它可以将物理内存和逻辑内存分开,从而使得程序可以使用比物理内存更大的地址空间。在Nachos中,我们可以使用页面替换算法来实现虚拟内存。 页面替换算法是一种将内存中的页面与硬盘中的页面进行交换的技术。当内存空间不足时,在Nachos中,我们可以选择将一部分不常用的页面从内存中换出到硬盘中,从而腾出内存空间来加载更多的页面。当需要访问被换出的页面时,我们可以将其从硬盘中换入到内存中,这样就可以实现对更大内存地址的访问。 在实验中,我们可以使用Nachos操作系统提供的一些接口来实现内存地址扩展。例如,我们可以使用Nachos的PageTable来管理页面的映射关系,使用TranslationEntry来表示页面的状态。我们还可以使用SwapSpace来管理页面的换入和换出。 总之,操作系统课设实验七主要涉及了Nachos内存地址扩展的实现。通过虚拟内存和页面替换算法,我们可以扩展Nachos操作系统的内存地址空间,以满足处理更大规模问题的需求。实验中,我们可以使用Nachos提供的接口来管理页面的映射、状态和换入换出操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌兮_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值