0%

NachOS实验之系统调用

在Ubuntu20.04,Nachos4.1环境下,实现系统调用。还不理解系统调用,只知道实现了从c文件到头文件到汇编指令代码的一步步编写,最后成功实现函数作用。

具体要求:模仿code/test/add.c,阅读并理解其实现过程,实现求乘法,除法、乘方三种系统调用。

修改文件

tips:所有的修改都参考已有的Add函数实现,参考博客(3条消息) Nachos系统调用的实现_零商的博客-CSDN博客_nachos系统调用原理与实现

code/userprog

syscall.h

添加宏定义(老人言:建议函数名取短一点)

1
2
3
#define SC_Multiplication	43	//added by sean
#define SC_Division 44 //added by sean
#define SC_Power 45 //added by sean

添加函数声明(注意除法的返回为double类型)

1
2
3
4
/////////////new add for division,mutiplication and power/////////
int Multiplication(int op1, int op2);
int Power(int op1, int op2);
double Division(int op1, int op2);

ksyscall.h

编写函数内容实现具体功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//////////new add function definition////
int SysMultiplication(int op1, int op2){
return op1*op2;
}

int SysPower(int op1, int op2){
int x=op1;
for(int i=1;i<op2;i++){
op1=op1*x;
}
return op1;
}

double SysDivision(int op1, int op2){
return 1.0*(op1/op2);
}

讲个笑话:我刚提醒注意double类型,就发现自己的函数返回类型是int……仍无法做到返回double类型,只能返回向下取整的数,why?等我学会了再来补充。

exception.cc

通过switch实现对不同指令的响应功能,以及对异常进行处理(注意不同case下的定义不同的result变量,division定义为double),仅贴division这一case,multiplication和power与add只有result不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
case SC_Division:
DEBUG(dbgSys, "Division " << kernel->machine->ReadRegister(4) << " + " << kernel->machine->ReadRegister(5) << "\n");

double result4;
result4 = SysDivision(/* int op1 */(int)kernel->machine->ReadRegister(4),
/* int op2 */(int)kernel->machine->ReadRegister(5));

DEBUG(dbgSys, "Division returning with " << result4 << "\n");
kernel->machine->WriteRegister(2, (double)result4);
{
kernel->machine->WriteRegister(PrevPCReg, kernel->machine->ReadRegister(PCReg));
kernel->machine->WriteRegister(PCReg, kernel->machine->ReadRegister(PCReg) + 4);
kernel->machine->WriteRegister(NextPCReg, kernel->machine->ReadRegister(PCReg)+4);
}
return;

ASSERTNOTREACHED();

break;

code/test

start.s

参照Add新增函数对应的汇编指令代码,注意一段的格式

1
2
3
4
5
6
7
	.globl Add
.ent Add
Add:
addiu $2,$0,SC_Add
syscall
j $31
.end Add

test.c

测试文件

1
2
3
4
5
6
7
8
9
10
#include "syscall.h"
int main(){
int resAdd,resMul,resPow;
double resDiv;
resAdd=Add(2,10);
resMul=Multiplication(2,10);
resPow=Power(2,10);
resDiv=Division(25,10);
Halt();
}

随便写,也可以随便命名,不过后面的改动也要按照自己的命名来操作。

Makefile

SOURCE行加入test.c

1
SOURCES = add.c halt.c matmult.c shell.c sort.c test.c

编译运行

1
2
3
4
5
6
7
8
9
10
#在code/test
make clean
make
#在code/build.linux
make clean
rm -rf nachos
make depend
make #是否有点眼熟
#在code/test
../build.linux/nachos -x test.noff -d u

计算结果如图:image-20220419210212324

可见division得到的结果并不准确(待解决)

Over

一些error

  • 在test中make遇到error时,可以看看报错信息,可能会提醒在Makefile的哪一行,然后一步步检查,可能

    • 单词拼写错误
    • 缩进错误(建议自己敲,不要CTRLCV)
  • 一个无语的errorcpp not found:检查半天发现是上一次装环境装到一半忘记了,我mips还没解压呢

  • 一个奇怪的error起源于vim编辑时非正常退出产生了swp文件,如何删除参考https://blog.csdn.net/daniaoday/article/details/80398831,经此错误,我更爱记事本和vscode了

    1
    rm filename.swp	#filename包含了后缀
  • 一个搞笑的error起源于逃课(错误行为请勿模仿),是在最后编译运行时,由于没听课就问室友最后一步是不是gcc编译运行,我也没问清楚,室友们也跟我不在一个频道上(以为我在说make那一步会不会用到gcc)纷纷说就是gcc,我以为的gcc是gcc test.c -o test,然后就一直报错嘛,要不是看了室友的实验报告我差点就要丢脸丢到助教面前了。。

总结

  • 做事尽量一次性完成
  • 不要逃课
  • 记得解决double的问题
  • 下次及时记录(懒:下次一定)