提示:看到的学弟学妹们不要想着copy哈,认真琢磨操作系统是一件非常有意思的事!
实验题目
提示:以下是本篇文章正文内容,下面步骤仅供参考
一、实验目的、环境
二、实验步骤
- 在/userprog/syscall.h中进行宏定义和函数声明
-
在/userprog/ksyscall.h中实现函数的功能
-
在mipssim.cc可看到nachos执行系统调用的方法是升起异常——调用中断处理函数。
因此下一步是在/userprog/exception.cc中通过switch实现对不同指令的响应功能,以及对异常进行处理。
此处仅以mul实例
- 在/test/start.s中补充汇编指令代码,实现系统调用
我们可以观察到Add函数的实现是将系统调用类型(type)SC_Add放入了2号寄存器中,然后执行syscall。因此直接模仿改写。
5.在test文件夹下增加test.c,实现函数调用
-
修改makefile 使得test.c正确编译
-
在/test路径下清除先前的编译结果,再make编译
-
在/build.linux路径下make进行全局编译并运行
总结
1.Nachos是什么?
Nachos (Not Another Completely Heuristic Operating System),是一个教学用操作系统,提供了操作系统框架:
- 线程
- 中断
- 虚拟内存(位图管理所有物理页,虚拟地址与物理地址之间的转换等)
- 同步与互斥机制(锁、条件变量、信号量),读者写者问题,生产者消费者问题,BARRIER问题等
- 线程调度(基于优先级可抢占式调度,时间片轮转算法,FIFO调度)
- 文件系统
- 系统调用
- 机器指令、汇编指令、寄存器
……
Nachos模拟了一个MIPS模拟器,运行用户程序。
2.预备知识
addiu $2 $0 SC_Write
即0号寄存器的值与SC_Write的调用号相加并存入2号寄存器,其中0号寄存器的值恒为0.
系统传递参数>4:x64汇编传递超过4个参数
返回值非整数:可采用指向返回字符串/结构体的指针。
3.文件结构分析
code/userprog/syscall.h:这里定义了Nachos中的系统调用号,以及相应的系统调用接口。Nachos目前共有11种系统调用。
code/userprog/exception.cc:这里定义了异常处理函数。当异常发生的时候,ExceptionHandler函数会被调用。系统调用也是异常的一种,即SyscallException。然后根据从寄存器中读到的系统调用号,来进行相应的处理。
code/test/start.s:用于辅助Nachos中用户程序的执行。该文件共有两个作用,其一是定义程序执行时跳转到main函数,以及程序执行结束时调用Exit系统调用。另一个作用是,实现了用户程序的系统调用接口,该接口会将参数放在寄存器中,并跳转到异常处理函数执行相应的处理。
4.nachos用户程序运行流程
4. ExceptionHandler()分析
//mul
case SC_Mul:
//终端输出信息
DEBUG(dbgSys, "Mul " << kernel->machine->ReadRegister(4) << " * " << kernel->machine->ReadRegister(5) << "\n");
/* Process SysMul Systemcall*/
int resultMul;
resultMul = SysMul(/* int op1 */(int)kernel->machine->ReadRegister(4),
/* int op2 */(int)kernel->machine->ReadRegister(5));
DEBUG(dbgSys, "Mul returning with " << resultMul << "\n");
/* Prepare Result */
//从2号寄存器中取值
kernel->machine->WriteRegister(2, (int)resultMul);
/* Modify return point */
//即PC+1
{
/* set previous programm counter (debugging only)*/
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
/* set programm counter to next instruction (all Instructions are 4 byte wide)*/
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
/* set next programm counter for brach execution */
//注意此时的PC以变成之前的NextPC
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg)+4);
}
return;
ASSERTNOTREACHED();
break;
后记
第一次认真写博客,希望能坚持。