当前位置: 首页 > java >正文

[山东大学操作系统课程设计]实验六

0.写在前面:

事先说明一点,在实验六开始,绝大多数的问题我应该都无法解释了,因为我自己做这个实验都是有点困难的,所以在接下来我不会过多阐述原理上的东西,只交待这个东西是怎么做的。

另外实验六七又是连在一起的因此。。。。。唉,没办法,一起写了呗

1.实验需求分析:

实验需求大致可以去分为如下几个步骤:

1.在APPSpace中实现两个系统调用,第一关是print方法,另一个是Exec方法,这两个方法可以实现一个用户程序启动另一个用户程序,类似linux中fork这个东西

2.在用户程序中打印一个整数数值,也就是新增一个系统调用PrintInt

3.尝试说明,如何实现类似linux下的fork函数,还有及写时复写机制的实现:

2.实验具体操作步骤:

复制文件:

我们需要复制一下文件到lab6文件夹(关于这个文件夹还有一些需要处理的地方,这个我们会在第四个模块详细解释一下)

addrspace:

对于地址空间这个类(关于进程和地址空间的关系,这里我就不多解释了)

新增两个声明方法

在具体的类中,首先进行原有方法的修改:

AddrSpace::AddrSpace(OpenFile *executable)
{NoffHeader noffH;unsigned int i, size;bool flag = false;                        //将物理页面分配给进程使用for(i = 0; i < NumPhysPages; i++) {if(!ProgMap[i]) {ProgMap[i] = true;flag = true;                    //成功找到可分配的物理页面,即可完成分配spaceID = i;                 break;}}ASSERT(flag);                          //断言检查是否存在可用的物理页面//如果没有分配到,则进行输出返回executable->ReadAt((char *)&noffH, sizeof(noffH), 0);if ((noffH.noffMagic != NOFFMAGIC) && (WordToHost(noffH.noffMagic) == NOFFMAGIC))SwapHeader(&noffH);ASSERT(noffH.noffMagic == NOFFMAGIC);// how big is address space?size = noffH.code.size + noffH.initData.size + noffH.uninitData.size + UserStackSize;	// we need to increase the size// to leave room for the stacknumPages = divRoundUp(size, PageSize);size = numPages * PageSize;ASSERT(numPages <= NumPhysPages);		// check we're not trying// to run anything too big --// at least until we have// virtual memoryDEBUG('a', "Initializing address space, num pages %d, size %d\n", numPages, size);
// first, set up the translation pageTable = new TranslationEntry[numPages];for (i = 0; i < numPages; i++) {pageTable[i].virtualPage = i;	// for TLB onlypageTable[i].physicalPage = freeMM_Map->Find();pageTable[i].valid = TRUE;pageTable[i].use = FALSE;pageTable[i].dirty = FALSE;pageTable[i].readOnly = FALSE;  // if the code segment was entirely on // a separate page, we could set its // pages to be read-only}// zero out the entire address space, to zero the unitialized data segment 
// and the stack segmentbzero(machine->mainMemory, size);// then, copy in the code and data segments into memoryif (noffH.code.size > 0) {DEBUG('a', "Initializing code segment, at 0x%x, size %d\n", noffH.code.virtualAddr, noffH.code.size);unsigned int code_page = noffH.code.virtualAddr / PageSize; //寻找开始页面unsigned int code_phy_addr = pageTable[code_page].physicalPage * PageSize;//使用页面和补偿计算物理地址executable->ReadAt(&(machine->mainMemory[code_phy_addr]), noffH.code.size, noffH.code.inFileAddr);//获取存储}if (noffH.initData.size > 0) {DEBUG('a', "Initializing data segment, at 0x%x, size %d\n", noffH.initData.virtualAddr, noffH.initData.size);unsigned int data_page = noffH.initData.virtualAddr / PageSize;//寻找数据起点页面unsigned int data_offset = noffH.initData.virtualAddr % PageSize;//第一个数据补偿的起点界面unsigned int data_phy_addr = pageTable[data_page].physicalPage * PageSize + data_offset;  //和上一个分支中的代码一样executable->ReadAt(&(machine->mainMemory[data_phy_addr]), noffH.initData.size, noffH.initData.inFileAddr);//同上}Print();
}//----------------------------------------------------------------------
// AddrSpace::~AddrSpace
// 	Dealloate an address space.
//----------------------------------------------------------------------AddrSpace::~AddrSpace()
{ProgMap[spaceID] = 0;       //在解析构造方法中作出一定的修改for (unsigned int i = 0; i < numPages; i++)   //清理对应的内存freeMM_Map->Clear(pageTable[i].physicalPage);delete [] pageTable;
}

实现print方法,addrspace这个类就基本结束工作

void AddrSpace::Print(void)       //实现了print方法
{printf("spaceID: %u\n", spaceID);printf("Page table dump: %d pages in total\n", numPages);printf("============================================\n");printf("VirtPage, PhysPage\n");for (unsigned int i = 0; i < numPages; i++)printf("     %3d,      %3d\n", pageTable[i].virtualPage, pageTable[i].physicalPage);printf("============================================\n\n");
}

exception:

在这个类中,对唯一的方法进行重写

void
ExceptionHandler(ExceptionType which)       //该方法根据不同的异常情况完成重写
{int type = machine->ReadRegister(2);if (which == SyscallException) {switch (type) {	case SC_Halt:DEBUG('a', "Shutdown, initiated by user program.\n");interrupt->Halt();break;case SC_Exec:interrupt->Exec();machine->WriteRegister(PrevPCReg, machine->ReadRegister(PCReg));   //虽然调用不一样但是底下的逻辑是差不多的machine->WriteRegister(PCReg, machine->ReadRegister(NextPCReg)); machine->WriteRegister(NextPCReg, machine->ReadRegister(NextPCReg) + 4); break;default:printf("Syscall %d not implemented\n", type);machine->WriteRegister(PrevPCReg, machine->ReadRegister(PCReg)); machine->WriteRegister(PCReg, machine->ReadRegister(NextPCReg)); machine->WriteRegister(NextPCReg, machine->ReadRegister(NextPCReg) + 4); break;}}else {printf("Unexpected user mode exception %d %d\n", which, type);ASSERT(FALSE);}
}

interrupt:

新增两个控制的方法:

在类中实现对于这两个方法的重构:

//执行一个用户进程void Interrupt::Exec(void)
{printf("Execute system call of Exec()\n");// read argumentchar fileName[50];int addr = machine->ReadRegister(4);int i = 0;do {machine->ReadMem(addr + i, 1, (int*) &fileName[i]); // read filename from mainMemory} while(fileName[i++] != '\0');printf("Exec(%s):\n", fileName); OpenFile *executable = fileSystem->Open(fileName);if (executable == NULL) {printf("Unable to open file %s to execute\n", fileName);return;}AddrSpace *space = new AddrSpace(executable);    delete executable;			// close execute fileThread *thread = new Thread(fileName);  // New thread for another user programthread->space = space;thread->Fork(RunProcess, (int)space->getSpaceID());currentThread->Yield();machine->WriteRegister(2, (int)space->getSpaceID());  // Return SpaceId
}//打印并且获得一个整数void Interrupt::PrintInt(int v)
{printf("%d\n", v);
}

system:

在宏定义也就是头文件中加入如下设定:

在cc文件中执行类似的操作即可

main:

最后将线程相关的宏定义修改为:

3.实验的测试工作:

编译以后按照指令进行调试

./nachos -x ../test/exec.noff

得到输出结果即为成功

4.遇到的问题:

好像没啥问题,哦对了注意一点

lab6这个文件名称最好不要改动,因为我发现不仅仅是local中用到了引用。。。

不过如果您头铁,当我另说

http://www.xdnf.cn/news/11165.html

相关文章:

  • Lifekeeper产品正版与盗版的区别
  • 数据库SQL入门教程基础知识
  • jsp的session介绍 (转)
  • 解决因找不到d3dx9_29.dll而无法运行程序的问题
  • 不兼容android5.1.1,为什么你的手机刷不上Android 5.1系统?需要具备哪些条件呢?...
  • 详解Oracle RAC入门和提高
  • 激光雷达运动畸变去除方法
  • Citrix VDI实战攻略之五:vDisk配置
  • CDN加速原理详解
  • 嵌入式TCP硬件设计--------LAN8720芯片使用记录
  • 开源web终端ssh解决方案-gateone简介
  • 创龙TMS320C6748开发板———EDMA简介及配置
  • 启动应用程序出现dxdiag.exe找不到问题解决
  • 路由器不能端口映射什么原因?如何设置内网映射?
  • 汇川触摸屏IT7000E和汇川中小型系列PLC连接及MW寄存器说明
  • 安装虚拟机(VMware)保姆级教程及配置虚拟网络编辑器和安装WindowsServer以及宿主机访问虚拟机和配置服务器环境
  • 用CSS绘制最常见的40种形状和基本图形
  • C#实现使用Timer组件实现世界杯倒计时(附完整源码)
  • 标准布朗运动的定义、代码和图像
  • 服务器端口怎么开放?
  • 动态发布站点的并发访问升级简易方案
  • 网工配置命令基础总结(2)----VRRP配置
  • 魔兽世界台服被大陆玩家挤爆
  • STM32单片机——看门狗(独立看门狗窗口看门狗)
  • Ajax的使用(详解)
  • linux命令、vi命令、vim命令、shell语法(完整详细)
  • Notepad++ 下载与安装教程(非常详细),从零基础入门到精通,看完这一篇就够了(附安装包)
  • 有哪些靠谱的短链接服务?主流大平台短链接优劣对比分析
  • 不知道怎么下载原版系统,这几个原版系统下载网站可以帮你
  • install 命令用法详解