1
Operating Systems Project 1
資工三 B94902032 陳縕儂、資工三 B94902007 張詩平
These files we have modified:
(1) code/test/start.S
Add the low level operation to support the new declared system call in the file.
The code for Exit has been already written.
(2) code/userprog/syscall.h
Define three new system calls (Square, Max, Print) in it.
Declare three new interfaces for Nachos system calls, which will be called by the user program.
此處Print傳進去的parameter是一個指向char的pointer,之後會在exception.cc中呼叫SysPrint,並且修改其parameter 的type。
.globl Max .ent Max Max:
addiu $2, $0, SC_Max syscall
j $31 .end Max
.globl Exit .ent Exit Exit:
addiu $2,$0,SC_Exit syscall
j $31 .end Exit .globl Square
.ent Square Square:
addiu $2, $0, SC_Square syscall
j $31 .end Square
.globl Print .ent Print Print:
addiu $2, $0, SC_Print syscall
j $31 .end Print
#define SC_Exit 1
#define SC_Square 43
#define SC_Max 44
#define SC_Print 45
/*
* op1 = op1^2 */
int Square(int op1);
/*
* op1 = max{op1, op2}
*/
int Max(int op1, int op2);
/*
* parse the parameter %d */
void Print(char *msg, int value);
/* This user program is done (status = 0 means exited normally). */
void Exit(int status);
2
(3) code/userprog/exception.cc
File exception.cc is the entry point into the Nachos kernel from user programs.
We write the handlers for system calls.
Since we have already defined new system calls in syscall.h, we can now read the arguments in Register4-7, and write the return value in Register 2.
We also set up the program counter for each system call here.
原先 Print 的第一個傳入值是一個指到 char 的 pointer,void Print(char *msg, int value);。但當呼叫 SysPrint 時,因為傳 入的第一個 parameter,是之後要被傳給 ReadMem 的第一個參數,而 type 必須是一個 int,然後存一個位置。所以將 一開始傳進來指到 char 的 parameter 轉成 int 傳給 SysPrint。
case SC_Square:
DEBUG(dbgSys, "Square " << kernel->machine->ReadRegister(4) << " ^2" << "\n");
/* Prcess SysSquare Systemcall*/
result = SysSquare((int)kernel->machine->ReadRegister(4));
DEBUG(dbgSys, "Square returning with " << result << "\n");
kernel->machine->WriteRegister(2, (int)result);
{
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;
case SC_Max:
DEBUG(dbgSys, "Max " << kernel->machine->ReadRegister(4) << " and" << kernel->machine->ReadRegister(5) <<"\n");
/* Prcess SysMax Systemcall*/
result = SysMax((int)kernel->machine->ReadRegister(4), (int)kernel->machine->ReadRegister(5));
DEBUG(dbgSys, "Max returning with " << result << "\n");
kernel->machine->WriteRegister(2, (int)result);
{
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;
case SC_Print:
/* Prcess SysPrint Systemcall*/
SysPrint((int)kernel->machine->ReadRegister(4), (int)kernel->machine->ReadRegister(5));
{
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;
case SC_Exit:
/* Prcess SysExit Systemcall*/
SysExit((int)kernel->machine->ReadRegister(4));
return;
ASSERTNOTREACHED();
break;
3
(4) code/userprog/ksyscall.h
We implement new system calls for Square, Max, Print and Exit here.
Print 的處理方式是將 msg 指到的東西 copy 到 ptr 中(以 char 的 type),每次都判斷兩個相鄰的位置是否為%d,如果是 的話,將此位置紀錄在 cut 中,然後將 flag 設為 1(避免下一個%d 再被重複做)。
將 cut 以前的 string 印出,然後再印出 value,再將%d 以後的 string 印出,即完成 Print 的 implementation。
(5) code/test/Makefile
This Makefile is used for user programs to run on top of Nachos.
Since we use user program (test.c) to test our newly-defined system call, we make a small modification in order to compile test.c and create a executable file by using the command "make".
int SysSquare(int op1) {
return op1 * op1;
}
int SysMax(int op1, int op2) {
if(op1 >= op2) return op1;
else
return op2;
}
void SysPrint(int msg, int value) {
char buffer[100] = {'\0'};
int ptr[4];
int i = 0, cut, flag = 0;
while(i < 100){
kernel->machine->ReadMem(msg + i, 1, ptr);
buffer[i] = ptr[0];
kernel->machine->ReadMem(msg + i + 1, 1, ptr);
if(buffer[i] == '%' && ptr[0] == 'd' && flag == 0){
cut = i;
flag = 1;
} i ++;
}
if(flag == 1){
for(i = 0; i < cut; i ++) printf("%c", buffer[i]);
printf("%d%s", value, buffer + i + 2);
} else
printf("%s", buffer);
return;
} void SysExit(int status)
{
exit(status);
return;
}
test.o: test.c
$(CC) $(CFLAGS) -c test.c test: test.o test.o
$(LD) $(LDFLAGS) start.o test.o -o test.coff $(COFF2NOFF) test.coff test