专业制作网站工业制品流程,网站制作实例,wordpress api.w.org,可以做四级听力的网站0.写在前面#xff1a;
为什么这次把两个实验放在一起写了#xff0c;因为实验五的要求就是在实验四的基础上完成实现的。但是我得实现说明#xff0c;我的实验四虽然完成了要求#xff0c;但是无法在我自己的实验四的基础上完成实验五#xff0c;这是一个很大的问题
为什么这次把两个实验放在一起写了因为实验五的要求就是在实验四的基础上完成实现的。但是我得实现说明我的实验四虽然完成了要求但是无法在我自己的实验四的基础上完成实验五这是一个很大的问题所以在这里将直接将实验四和实验五统一进行讲解和处理。
由于后续时间不足因此实验四开始全部的东西将完全使用报告的形式来进行演示。在一些我遇到坑的地方我会告诉大家怎么样处理当然仅此而已了。。。。。
对不起啦D
小三爷你大胆的往前走莫回头
其实说真的我的本职工作是写小说的或许未来的某天我会试着重新开始写我想写的东西。
1.实验要求四五
1.实验四
实验四的要求按照2021级的要求大概就是这些了
1. 扩展nachos的文件大小
2. 增加文件的修改时间
其实对于这个实验来说这个实验就是一个分水岭了接下来该怎么做就算是抄也要对源码部分有一定的理解才可以了。
2.实验五
实验五的要求总结一下大致如下
0.在实验四的基础上实现
1.实现二级索引
2.增加-DI指令可以输出磁盘的占用状态
3.尝试并解释如何为nachos加上权限实现不要求代码实现
其实可以看出来核心就在于两个实验各自的第一条但是这个实验难搞的点就在于我们需要百分百保证实验四的可行性而实验手册对于这个的讲解其实非常混乱因此我们在这里的实验步骤是一次性完成实验四五的大家可以按需所需这个过程中需要什么可以直接选择如果是全篇可以拿去当实验五的完整步骤
ok那么我们开始
2.实验步骤
首先将图中对应文件移动进入lab5文件夹 filehdr类
在h头文件中加入以下声明 并且在对应的类中加入如下属性以及方法 注意这里给print加上了一个参数默认这个参数我们会后续说明怎么修改print下面的方法属于我们的添加 在filehdr.cc文件中实现对于这些功能的声明
在这里直接写出对于对应方法的修改自行取用
方法新增
对于构造和解析方法
FileHeader::FileHeader(){memset(dataSectors, 0, sizeof(dataSectors));bHdrChangefalse;lastModTime0;
}
FileHeader::~FileHeader(){if(bHdrChange){WriteBack(sectorNo);}
}
对于expendSize方法
//申请新的扇区的方法
bool
FileHeader::ExtendSpace(int newFileSize){ int i;if(newFileSizenumBytes)return true;int numSectorsSetdivRoundUp(newFileSize,SectorSize); //计算新的扇区位置if(numSectorsSetnumSectors){numBytes newFileSize;bHdrChange true;return true;}BitMap * freeMap new BitMap(NumSectors);OpenFile * bitMapFilenew OpenFile(0);freeMap-FetchFrom(bitMapFile);if(numSectorsSetMaxFileSectors||freeMap-NumClear()numSectorsSet-numSectors){ //超过最大限度或者是不合适//经过答案提示需要删除点东西维持系统的稳定性吧delete bitMapFile;delete freeMap;return false;}if(numSectorsSetNumDirect){ //不需要二级索引的情况 for(int inumSectors;inumSectorsSet;i){ dataSectors[i] freeMap-Find(); }}else{ //需要二级索引的情况if(numSectorsNumDirect){for(int inumSectors;iNumDirect;i){dataSectors[i] freeMap-Find(); }numSectorsNumDirect;}int dataSectors2[NumDirect2];synchDisk-ReadSector(dataSectors[NumDirect],(char *)dataSectors2);for(i0;i numSectorsSet-numSectors;i){dataSectors2[inumSectors-NumDirect]freeMap-Find();}synchDisk-WriteSector(dataSectors[NumDirect],(char *)dataSectors2);}freeMap-WriteBack(bitMapFile);numBytesnewFileSize;numSectorsnumSectorsSet;bHdrChangetrue;delete bitMapFile;delete freeMap;return true;
}
关于修改时间的参数
//关于时间新增的方法如下
//这两个方法为文件头这个对象加上了些许时间属性。
time_t FileHeader::GetModTime(){return (time_t)lastModTime;
}
void FileHeader::SetModTime(time_t modTime){lastModTime(unsigned)modTime;
}
关于代码的重写
首先是空间分配的方法
bool
FileHeader::Allocate(BitMap *freeMap, int fileSize) //这个方法可能只是用于最开始分配空间而已了。。。。
{ printf(\n分配空间\n);int i;numBytes fileSize; //确定文件的大小numSectors divRoundUp(fileSize, SectorSize); //根据文件大小和每个盘的尺寸确定要分几个盘if (freeMap-NumClear() numSectors)return FALSE; // not enough space 空间不足else if(NumDirect2NumDirectnumSectors)return FALSE; // 超过了二级索引所能容纳的最大部//然后接下来分成两种情况也就是看看是否超过了最后一层的索引,根据这种情况来完成需要的分配 //应该就是这里设置了-1这个东西if(numSectorsNumDirect){for (int i 0; i numSectors; i)dataSectors[i] freeMap-Find();//这个时候按照要求因为没有用上二级的索引因此最后一个指向二级索引的块应该为-1dataSectors[NumDirect]-1;//打印当前信息printf(numSector:%d . numBytes:%d . lastIndex:%d\n,numSectors,numBytes,NumDirect);}else{for (int i 0; i NumDirect; i) //更改2,这个位置写错了dataSectors[i] freeMap-Find();int dataSectors2[NumDirect2];for (int i 0; i numSectors - NumDirect; i)dataSectors2[i] freeMap-Find();//将结果写回,就算成功了synchDisk-WriteSector(dataSectors[NumDirect],(char *)dataSectors2);}//return true;
}撤销空间分配的方法
void
FileHeader::Deallocate(BitMap *freeMap) //在释放空间这一步需要回收二级列表
{int lastIndexNumDirect;if(dataSectors[lastIndex]-1){ //for (int i 0; i numSectors; i) {ASSERT(freeMap-Test((int) dataSectors[i])); // ought to be marked!freeMap-Clear((int) dataSectors[i]);}}else{for (int i 0; i lastIndex; i) {ASSERT(freeMap-Test((int) dataSectors[i])); // ought to be marked!freeMap-Clear((int) dataSectors[i]);}int dataSectors2[NumDirect2];synchDisk-ReadSector(dataSectors[lastIndex],(char *)dataSectors2);freeMap-Clear(dataSectors[lastIndex]);for (int i lastIndex; i numSectors; i) {ASSERT(freeMap-Test((int) dataSectors2[i-lastIndex])); // ought to be marked!freeMap-Clear((int) dataSectors2[i-lastIndex]);}}}
根据扇区号码拉取和写回的方法
void
FileHeader::FetchFrom(int sector)
{synchDisk-ReadSector(sector, (char *)this);numSectorsdivRoundUp(numBytes,SectorSize);sectorNosector;bHdrChangefalse;
}//----------------------------------------------------------------------
// FileHeader::WriteBack
// Write the modified contents of the file header back to disk.
//
// sector is the disk sector to contain the file header
//----------------------------------------------------------------------void
FileHeader::WriteBack(int sector)
{//在这里修改时间即可synchDisk-WriteSector(sector, (char *)this); sectorNosector;bHdrChangefalse;
}print方法
void //这个是打印具体文件信息的方法
FileHeader::Print(bool bPrintTime)
{int i, j, k;char *data new char[SectorSize];//临时测试//lastTime(unsigned)std::time(nullptr); //段错误就这段代码引起的if(bPrintTime){printf(FileHeader contents\n. File size: %d. lastModTime: %u . File blocks:\n,numBytes,lastModTime);}else{printf(FileHeader contents\n. File size: %d. File blocks:\n, numBytes);} //这里加上两种情况来输出所占的块的数目int lastIndexNumDirect;if(dataSectors[lastIndex]-1){ //仅仅占用了一个索引for (i 0; i numSectors; i)printf(%d , dataSectors[i]);printf(\n没有使用二级索引\n);}else{ //占用了所有的索引 printf(一级索引内容\n);for (i 0; i lastIndex; i)printf(%d , dataSectors[i]);printf(\n二级索引内容\n);int dataSectors2[NumDirect2];synchDisk-ReadSector(dataSectors[lastIndex],(char*)dataSectors2);for (; i numSectors; i)printf(%d , dataSectors2[i-lastIndex]); //为什么这里会一直认为是-1呢printf(\n确定使用二级索引索引地址为%d\n,dataSectors[lastIndex]);}//printf(\nFile contents:\n);for (i k 0; i numSectors; i) {synchDisk-ReadSector(dataSectors[i], data);for (j 0; (j SectorSize) (k numBytes); j, k) {if (\040 data[j] data[j] \176) // isprint(data[j])printf(%c, data[j]);elseprintf(\\%x, (unsigned char)data[j]);}printf(\n); }delete [] data;
}然后是对于openfile类的修改
openfile
首先是对于头文件中的声明
新增一个写回方法 属性增加这些 接下来是对实现的一个修改
首先是对于构造方法的修改如下
OpenFile::OpenFile(int sector) //文件读取器的创建
{ hdr new FileHeader;hdr-FetchFrom(sector);seekPosition 0;// 修改时间hdr-SetModTime((unsigned)std::time(nullptr));hdrSectorsector;
}读和写的方法大概是这些我在这里主要添加了关于时间修改的函数
int
OpenFile::Read(char *into, int numBytes) //读写文件
{int result ReadAt(into, numBytes, seekPosition);seekPosition result;// 修改时间hdr-SetModTime((unsigned)std::time(nullptr));return result;
}int
OpenFile::Write(char *into, int numBytes)
{int result WriteAt(into, numBytes, seekPosition);seekPosition result;// 修改时间hdr-SetModTime((unsigned)std::time(nullptr));return result;}
在writeAt方法上作出改进
int
OpenFile::WriteAt(char *from, int numBytes, int position) //最后是在这个方法上进行一些小小的改进
{int fileLength hdr-FileLength();int i, firstSector, lastSector, numSectors;bool firstAligned, lastAligned;char *buf;//if ((numBytes 0) || (position fileLength)) // For original Nachos file system// For lab4 ...if ((numBytes 0)|| position fileLength) return 0; if ((positionnumBytes) fileLength)if(!(hdr-ExtendSpace(positionnumBytes)))numBytesfileLength-position;if(fileLength0) return 0;DEBUG(f, Writing %d bytes at %d, from file of length %d.\n, numBytes, position, fileLength);firstSector divRoundDown(position, SectorSize);lastSector divRoundDown(position numBytes - 1, SectorSize);numSectors 1 lastSector - firstSector;buf new char[numSectors * SectorSize];firstAligned (bool)(position (firstSector * SectorSize));lastAligned (bool)((position numBytes) ((lastSector 1) * SectorSize));// read in first and last sector, if they are to be partially modifiedif (!firstAligned)ReadAt(buf, SectorSize, firstSector * SectorSize); if (!lastAligned ((firstSector ! lastSector) || firstAligned))ReadAt(buf[(lastSector - firstSector) * SectorSize], SectorSize, lastSector * SectorSize); // copy in the bytes we want to change bcopy(from, buf[position - (firstSector * SectorSize)], numBytes);// write modified sectors backfor (i firstSector; i lastSector; i) synchDisk-WriteSector(hdr-ByteToSector(i * SectorSize), buf[(i - firstSector) * SectorSize]);delete [] buf;hdr-SetModTime((unsigned)std::time(nullptr)); // 修改时间return numBytes;
}最后实现写回方法
void
OpenFile::WriteBack(void){ //给文件头部设置扇区号hdr-WriteBack(hdrSector);
}directory:
我好像是直接加入了这个方法
int Directory::GetHdrSecByIndex(int index){if(table[index].inUse){return table[index].sector;}else{return -1;}
}
filesys
在这个类中我们只需要实现一个打印的方法来帮助我们实现需要的-DI指令获取文件信息的操作
首先在头文件的声明中加入 然后直接实现这个方法即可
void FileSystem::PrintInfo(){BitMap *freeMapnew BitMap(NumSectors);Directory *directorynew Directory(NumDirEntries);FileHeader *fileHdr new FileHeader();int i, nBytes;int fileHdrSector;int nUsedSector, nFiles 0, nBytesInFiles0,nSectorsOfFiles0,nFragSectors0;printf(\n磁盘尺寸%d个扇区字节数目%d\n,NumSectors,NumSectors*SectorSize);freeMap-FetchFrom(freeMapFile);nUsedSector NumSectors - freeMap-NumClear();printf(\n(已经使用)%d个扇区字节数目%d\n,nUsedSector,nUsedSector*SectorSize);printf(\n未使用%d个扇区字节数目%d\n,freeMap-NumClear(),freeMap-NumClear()*SectorSize);directory-FetchFrom(directoryFile);for(i 0; i NumDirEntries; i) {fileHdrSector directory-GetHdrSecByIndex(i);if(fileHdrSector ! -1) {nFiles;fileHdr-FetchFrom(fileHdrSector);nBytes fileHdr-FileLength();nBytesInFiles nBytes;nSectorsOfFiles divRoundUp(nBytes, SectorSize);if(nBytes % SectorSize)nFragSectors;}}printf(%d bytes in %d files, occupy %d bytes(%d sectors).\n, \nBytesInFiles, nFiles, nSectorsOfFiles * SectorSize, nSectorsOfFiles);printf(%d bytes of internal fragmentation in %d sectors.\n, \nSectorsOfFiles * SectorSize - nBytesInFiles, nFragSectors);delete freeMap;delete directory;delete fileHdr;
}
main:
最后在这个入口文件中新增这样一个分支 到此为止所有的代码全部修改完毕
3.实验汇总
关于代码的执行
首先使用如下指令初始化并且复制一个big文件
make
rm -f DISK//初始化磁盘
./nachos -f
然后使用cp指令创建big文件
./nachos -cp test/big big
使用./nachos -D查询当前文件的状态
可以看到已经创建了big文件 此时使用指令
./nachos -ap test/big big
执行多次以后可以检查到最后的修改时间被更新并且已经实现了二级索引 最后使用指令
./nachos -D
查看占用情况 最后是关于为nachos添加wxz等权限 在Nachos的文件系统中每个文件都有一个相应的文件描述符File Descriptor用于标识和操作该文件。 使用文件描述符打开文件并获取文件的当前权限。在Nachos中可以使用 OpenFile::Open 函数打开文件并使用 OpenFile::GetFileHeader 函数获取文件的文件头File Header信息。 在文件头中找到与权限相关的位比如读、写、执行位并根据需要修改这些位。可以使用位操作来设置或清除相应的权限位。 将修改后的文件头写回到文件系统中以保存更改后的权限。可以使用 OpenFile::WriteAt 函数将文件头写回磁盘中的相应位置。 关闭文件并释放相关资源。使用 OpenFile::Close 函数关闭文件
4.可能会踩坑的问题
我这里只说一个我在实验四里面遇到的一个大问题就是这个3到底含义是什么 答案就是nachos的文件头需要存储在一个sector的内部但是一个磁盘内的容量仅仅为128字节而我们需要存入的是这些东西 这些东西是按照顺序存储的如果这些东西超过了128字节那就没救了
因此我们需要适当修改数组的大小因此在定义NumDirect的时候是根据我们需要存储的其他变量的大小修改数组的长度
5.补充我自己的实验四实现等待补充