news 2026/7/12 6:45:23

Nachos 文件系统实验四+五:FileHeader 二级索引与 -DI 指令实现 3 大核心修改

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nachos 文件系统实验四+五:FileHeader 二级索引与 -DI 指令实现 3 大核心修改

Nachos 文件系统实验:二级索引与磁盘状态查询的深度实现

在操作系统课程设计中,Nachos作为一个经典的教学实验平台,其文件系统模块的实现一直是学生深入理解存储管理原理的重要实践。本文将聚焦实验四和实验五中关于文件系统核心数据结构FileHeader的改造,特别是二级索引的实现和磁盘状态查询指令-DI的添加,从技术实现角度提供可落地的解决方案。

1. FileHeader 结构改造与二级索引设计

传统的Nachos文件系统采用直接索引方式管理文件数据块,这限制了文件的最大尺寸。我们需要通过二级索引扩展文件容量,同时保持系统的兼容性。

1.1 数据结构关键修改

filehdr.h中新增以下字段定义:

#define NumDirect 10 // 一级索引项数 #define NumDirect2 32 // 二级索引项数 #define MaxFileSectors (NumDirect + NumDirect2) // 最大支持扇区数 class FileHeader { private: int dataSectors[NumDirect+1]; // 最后一项存储二级索引块地址 unsigned lastModTime; // 最后修改时间戳 bool bHdrChange; // 脏位标记 int sectorNo; // 头部所在扇区号 };

核心改造点说明

  1. dataSectors数组扩容1项用于存储二级索引块地址
  2. 新增lastModTime记录文件修改时间
  3. 引入脏位机制减少磁盘写入

1.2 空间扩展函数实现

以下是关键的ExtendSpace函数实现,展示如何处理二级索引分配:

bool FileHeader::ExtendSpace(int newFileSize) { int numSectorsSet = divRoundUp(newFileSize, SectorSize); if(numSectorsSet <= numSectors) return true; BitMap *freeMap = new BitMap(NumSectors); OpenFile *bitMapFile = new OpenFile(0); freeMap->FetchFrom(bitMapFile); // 空间不足检查 if(numSectorsSet > MaxFileSectors || freeMap->NumClear() < numSectorsSet-numSectors) { delete bitMapFile; delete freeMap; return false; } if(numSectorsSet <= NumDirect) { // 仅需一级索引 for(int i=numSectors; i<numSectorsSet; i++) dataSectors[i] = freeMap->Find(); } else { // 需要二级索引 if(numSectors < NumDirect) { // 先填满一级索引 for(int i=numSectors; i<NumDirect; i++) dataSectors[i] = freeMap->Find(); numSectors = NumDirect; } // 处理二级索引块 int dataSectors2[NumDirect2]; if(dataSectors[NumDirect] == -1) { // 首次使用二级索引 dataSectors[NumDirect] = freeMap->Find(); memset(dataSectors2, -1, sizeof(dataSectors2)); } else { synchDisk->ReadSector(dataSectors[NumDirect], (char *)dataSectors2); } // 分配二级索引项 for(int i=0; i<numSectorsSet-numSectors; i++) dataSectors2[i] = freeMap->Find(); synchDisk->WriteSector(dataSectors[NumDirect], (char *)dataSectors2); } freeMap->WriteBack(bitMapFile); numBytes = newFileSize; numSectors = numSectorsSet; bHdrChange = true; delete bitMapFile; delete freeMap; return true; }

关键提示:二级索引块本身也占用一个扇区,需要在位图中标记。写入操作后必须立即更新磁盘上的位图信息。

2. 文件修改时间追踪实现

为支持文件修改时间记录,需要在关键操作点添加时间戳更新:

// 在filehdr.h中添加时间接口 time_t GetModTime() { return (time_t)lastModTime; } void SetModTime(time_t modTime) { lastModTime = (unsigned)modTime; bHdrChange = true; } // 在OpenFile类的读写操作中更新时间 int OpenFile::WriteAt(char *from, int numBytes, int position) { // ...原有写入逻辑... hdr->SetModTime((unsigned)std::time(nullptr)); return numBytes; }

时间戳存储采用Unix时间戳格式(32位无符号整数),在文件头回写磁盘时自动持久化。

3. 磁盘状态查询指令实现

-DI指令需要统计磁盘的整体使用情况,包括:

统计项说明
总扇区数NumSectors
已使用扇区位图中已标记的扇区
文件占用扇区所有文件实际使用的扇区数
内部碎片文件末扇区的未使用空间

实现代码如下:

void FileSystem::PrintInfo() { BitMap *freeMap = new BitMap(NumSectors); Directory *directory = new Directory(NumDirEntries); FileHeader *fileHdr = new FileHeader(); freeMap->FetchFrom(freeMapFile); directory->FetchFrom(directoryFile); // 基础统计 printf("\n磁盘尺寸:%d扇区 (%d字节)\n", NumSectors, NumSectors*SectorSize); printf("已使用扇区:%d (%.1f%%)\n", NumSectors-freeMap->NumClear(), 100*(NumSectors-freeMap->NumClear())/(float)NumSectors); // 文件详细统计 int nFiles=0, nBytesInFiles=0, nSectorsOfFiles=0, nFragSectors=0; for(int i=0; i<NumDirEntries; i++) { int sector = directory->GetHdrSecByIndex(i); if(sector != -1) { nFiles++; fileHdr->FetchFrom(sector); int bytes = fileHdr->FileLength(); nBytesInFiles += bytes; int sectors = divRoundUp(bytes, SectorSize); nSectorsOfFiles += sectors; if(bytes % SectorSize) nFragSectors++; } } printf("\n文件统计:\n"); printf(" 文件数量:%d\n", nFiles); printf(" 总文件大小:%d字节 (占用%d扇区)\n", nBytesInFiles, nSectorsOfFiles); printf(" 内部碎片:%d字节 (分布在%d个扇区)\n", nSectorsOfFiles*SectorSize - nBytesInFiles, nFragSectors); delete freeMap; delete directory; delete fileHdr; }

4. 实验验证与调试技巧

验证二级索引是否生效的测试方法:

  1. 创建测试文件并逐步扩展:
./nachos -cp test/big big ./nachos -ap test/big big # 多次执行直至触发二级索引
  1. 检查文件头信息:
./nachos -D
  1. 关键调试技巧:
  • FileHeader::Print()中添加索引类型输出
  • 使用hexdump -C DISK查看磁盘实际布局
  • 添加调试输出检查扇区分配顺序

常见问题解决方案

  1. 文件头大小超过128字节:调整NumDirectNumDirect2的比值
  2. 二级索引块未正确初始化:确保新分配的索引块全部初始化为-1
  3. 时间戳不更新:检查bHdrChange标记是否在修改后设置为true

通过以上实现,Nachos文件系统获得了动态扩展能力,同时提供了更完善的磁盘状态监控功能。这种改造方式既保持了原有架构的简洁性,又扩展了系统的实用性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 6:44:52

AI如何自动识别什么情况下会被认定为串标串标风险?智能评审项目实践

核心回答存在投标人相互串通报价、约定中标人、由同一主体制作文件或其他异常关联证据时&#xff0c;可能被认定串标&#xff0c;需要结合完整证据链判断。判断时要看哪些依据逐条提取暗标、格式和电子文件制作要求。检查企业识别信息、文档属性和模板残留。最终以转换后的上传…

作者头像 李华
网站建设 2026/7/12 6:44:15

TracePro 2024 光学仿真:多焦点菲涅尔透镜 3 种材料透光率与光强分布对比

TracePro 2024 光学仿真&#xff1a;多焦点菲涅尔透镜材料透光率与光强分布深度解析 在光学系统设计中&#xff0c;菲涅尔透镜因其轻薄、高效的特点被广泛应用于照明、投影和聚光等领域。而多焦点菲涅尔透镜通过精心设计的环带结构&#xff0c;能够在目标面上形成特定的光强分布…

作者头像 李华
网站建设 2026/7/12 6:42:03

Vivado 2023.1 工程归档实战:3步Tcl脚本压缩,存储空间减少99%

Vivado工程归档革命&#xff1a;TCL脚本驱动的极致空间优化与版本管理在FPGA开发领域&#xff0c;Vivado工程的体积膨胀是个令人头疼的普遍问题。一个中等复杂度的项目经过多次迭代后&#xff0c;工程文件夹可能轻松突破几个GB——这不仅仅是存储空间的浪费&#xff0c;更严重影…

作者头像 李华
网站建设 2026/7/12 6:40:52

惊了!原来论文还能这样搞定?2026降AIGC网站推荐合集

还在为查重太高、AI痕迹明显、格式乱成一团而发愁&#xff1f;2026 年的论文写作工具已经全面升级&#xff0c;从选题构思到降AIGC率、去AI痕迹、格式排版&#xff0c;全流程智能优化&#xff0c;帮你把论文写得又快又好&#xff0c;轻松应对毕业季&#xff01; 一、核心工具 T…

作者头像 李华
网站建设 2026/7/12 6:39:54

端到端自动驾驶10篇高推荐度论文深度解析

1. 项目概述&#xff1a;为什么这10篇论文值得你花30分钟精读一遍“理想一篇论文入选近半年端到端自动驾驶推荐度最高的10篇论文”——这个标题乍看像某平台的榜单推送&#xff0c;但背后藏着一个正在剧烈重构的技术拐点。我从2019年起跟进自动驾驶算法演进&#xff0c;全程参与…

作者头像 李华
网站建设 2026/7/12 6:38:42

`co_await` 按下暂停键之后:从零看懂 C++20 协程

协程最迷人的地方&#xff0c;是它能用接近同步代码的写法表达异步流程&#xff1a; auto data co_await socket.read(); auto result parse(data); co_await socket.write(result);代码从上到下&#xff0c;像普通函数一样自然&#xff1b;但等待网络数据时&#xff0c;线程…

作者头像 李华