Nachos系统调用实习报告解析Word下载.docx

上传人:b****2 文档编号:14868407 上传时间:2022-10-25 格式:DOCX 页数:22 大小:1,020.03KB
下载 相关 举报
Nachos系统调用实习报告解析Word下载.docx_第1页
第1页 / 共22页
Nachos系统调用实习报告解析Word下载.docx_第2页
第2页 / 共22页
Nachos系统调用实习报告解析Word下载.docx_第3页
第3页 / 共22页
Nachos系统调用实习报告解析Word下载.docx_第4页
第4页 / 共22页
Nachos系统调用实习报告解析Word下载.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

Nachos系统调用实习报告解析Word下载.docx

《Nachos系统调用实习报告解析Word下载.docx》由会员分享,可在线阅读,更多相关《Nachos系统调用实习报告解析Word下载.docx(22页珍藏版)》请在冰豆网上搜索。

Nachos系统调用实习报告解析Word下载.docx

总体概述

自lab4我们完成了虚拟内存的实习,可以运行用户程序之后,我们就考虑加入系统调用。

即,用户程序可以通过特定的系统调用,陷入Nachos内核,从而完成特定的目标。

本次lab一共要求完成10个系统调用,包括两大部分,文件系统相关——Create,Open,Close,Read,Write;

用户程序相关——Exec,Fork,Yield,Join,Exit。

需要在阅读和理解源码的基础上,知道系统调用的执行流程,进一步修增源代码,实现新增的系统调用功能。

任务完成情况

任务完成列表(Y/N)

Exercise1

Exercise2

Exercise3

Exercise4

Exercise5

Yes

具体Exercise的完成情况

Exercise1:

源代码阅读

任务:

阅读与系统调用相关的源代码,理解系统调用的实现原理。

完成情况:

1.Syscall.h

概述:

1)定义了每个系统调用对应的系统调用号

2)声明了每个系统调用

2.Exception.cc

对系统陷入进行处理。

1)从machine的2号寄存器读入系统调用号

2)执行对应的操作代码(需要自己完成)

3)(如果需要)将返回值写回Machine的2号寄存器

3.Start.s

当用户程序执行一个系统调用的时候,将参数放入2号寄存器,然后跳转到exception.cc执行。

以Halt为例:

将系统调用号放入2号寄存器

4.总结

当用户希望执行一条系统调用的时候:

1)在用户程序中调用

2)当这条语句被OneInstruction函数解析执行时,会判断出这是一条系统调用,转入start.s

3)在start.s中找到系统调用对应的入口(可能需要自己增加),将系统调用号放入machine的2号寄存器,并转入exception.cc

4)在exception.cc中,读出2号寄存器中的系统调用号,执行对应操作

5)必要时,将返回值写回2号寄存器,并注意,将PC前进。

6)指令回到用户程序系统调用的下一条继续执行。

系统调用完成。

为了执行一条系统调用,我们需要完成的部分:

1)

第一步:

增加需要编译的文件名称。

这两个是我新增的

自己写一个用于测试的用户程序的.c文件,并修改test的Makefile,使得用户程序能够被Nachos系统执行。

第二步,增加如何编译的信息。

2)因为本次lab需要写的系统调用,在start.s中都已经写好了,因此我们不需要修改。

同样,syscall.h中,系统调用号和函数声明也都写好了。

(但如果希望自己新增系统调用,这两个文件是需要修改的,修改方式可以参照别的系统调用)

3)补充exception.cc,执行对应的系统调用操作。

Exercise2:

系统调用实现

类比Halt的实现,完成与文件系统相关的系统调用:

Create,Open,Close,Write,Read。

Syscall.h文件中有这些系统调用基本说明。

Exercise3:

编写用户程序

编写并运行用户程序,调用练习2中所写系统调用,测试其正误。

EX2+EX3完成情况:

首先,在完成了文件系统的lab之后,为了能够让userprog编译通过,需要修改system.h的makefile,多include几个头文件以及声明extern变量。

否则,会出现:

undefinedreference***这种情况。

其次,我们需要在exception.cc中,加入系统调用入口:

1.voidCreate(char*name)

1)从4号寄存器读入文件名指针

2)利用指针,从Machine的mainmemory(内存)中,读出文件名

3)用文件名为参数,调用filesystem的create函数,创建文件(默认长度256byte)

4)将PC前移:

(machine.cc中定义)

代码:

(从内存中读出文件名部分)

测试截图:

之后在userprog文件夹下,就出现了a.txt这个文件(因为我是用UNIX的文件系统来做这次lab的)

2.OpenFileIdOpen(char*name)

1)从4号寄存器读入文件名指针

3)用文件名为参数,调用filesystem的open函数,打开文件,返回OpenFile指针(在Nachos系统中,OpenFile相当于是文件描述符)

4)将OpenFile指针写回machine的2号寄存器(machine->

WriteRegister(2,(int)openfile))

5)PC前移

(Openfile写回部分)

测试截图:

(打开失败)(Open成功会配合之后的系统调用再进行测试截图)

3.voidClose(OpenFileIdid)

1)从4号寄存器中读出OpenFile的指针

2)调用filesystem的close方法,将openfile关闭(自己编写的close方法,其中将传入的OpenFile指针delete掉)

3)PC前移

(从寄存器中读出Openfile指针+关闭部分)

(Close配合open系统调用测试截图)

注意:

打开文件返回的文件指针,和关闭文件时读取的文件指针相同。

关闭文件

打开文件

创建文件

4.intRead(char*buffer,intsize,OpenFileIdid)

1)从4号寄存器读出来装载字符串的指针

2)从5号寄存器读出需要读取的字符串长度

3)从6号寄存器读出OpenFile的指针

4)调用openfile的read函数,从光标位置读出一定长度的字符串,存入临时数组当中

5)将读出来的内容,写回machine的mainmemory中,写入的位置就是字符串指针依次往后。

6)将openfile的read函数的返回值,写入2号寄存器当中。

(见write部分,二者配合测试。

5.voidWrite(char*buffer,intsize,OpenFileIdid)

4)从machine的mainmemory中,从字符串指针位置开始,连续读出字符串长度个字符

5)将读出来的内容,调用OpenFile的write方法,写入文件当中。

a)单独测试write

成功写入希望写入的内容

b)配合read一起测试

字符的起始位置都是一样的。

打开文件b,将a读取的内容写入b(指针也相同~)

打开文件a,读取文件a(指针相同)

Exercise4:

实现如下系统调用:

Exec,Fork,Yield,Join,Exit。

Exercise5:

编写并运行用户程序,调用练习4中所写系统调用,测试其正确性。

EX4+EX5完成情况:

首先,为了能够使得Join和Exec的系统调用,能够在父子进程之间发生联系,我们需要在thread.h中加入Thread*childThread[MaxThreadSize],用于记录当前线程的子线程的thread指针。

这个数组在thread的构造函数中初始化,初始值均为NULL。

还需要加入Thread*fatherThread变量,用于记录当前线程的父线程(如果存在)。

同样在构造函数中进行初始化,初始赋值为自己。

1.SpaceIdExec(char*name))

1)从4号寄存器中读出名字指针,并仿照EX2中的做法,从mainmemory中获得名字。

2)新创建一个线程

3)在当前线程的childThread数组中,寻找是否还有空位,如果有,赋值给新创建的线程,标明父子关系,并且将新线程的指针号写回2号寄存器。

接着,将新创建线程的fatherThread指针赋值为currentThread。

新线程这时可以调用Fork,执行一段代码。

最后,PC前移

4)如果没有空位,输出错误信息,将PC前移。

5)Fork执行的代码:

参照progtest中,startprocess函数,先是打开这个用户程序文件,然后新创建一个地址空间,接着初始化machine,最后让machine->

run。

a)Fork之后调用的函数:

b)处理系统调用的代码:

(和之后的join+exit一起测)

2.intJoin(SpaceIdid)

1)从4号寄存器中读出要等待的子线程的OpenFile指针

2)找到自己的childThread数组中,这个OpenFile指针对应的位置

3)While循环,当这个位置不为NULL时,调用currentThread->

Yield(),等待子线程结束

4)跳出while循环后,将子线程的结束状态写入2号寄存器,PC前移

(配合Exec和Exit一起测)

3.voidExit(intstatus)

1)由于lab4虚拟内存中,需要在exit系统调用中释放page和清空tlb,因此此处继续保留这两个功能。

2)判断:

如果当前exit的线程不是主线程:

如果当前线程有父线程,将父线程中对应的自己设置为NULL(表明自己已经要退出啦!

),并且调用currentThread->

Finish()

3)如果是主线程:

PC前移

(配合之前的Exec和Exit)

a)测试函数:

Mytest函数:

b)测试截图:

主线程此时执行完了Exec,开始执行Join系统调用。

由于在等待的子线程还未结束,于是让位CPU

由于时间片到了,此时切换到主线程

准备在新线程的新的用户空间中运行Mytest

新线程创建自己的用户空间

新Fork出来的线程(设置优先级更高,于是立即抢占)切换

主线程执行Exec系统调用

主线程调用Exit退出。

新线程执行完毕了,切换到主线程。

主线程由于上次PC没前移,于是再次调用Join。

此次成功了。

新线程执行mytest中的内容:

Create一个文件,然后Exit退出(EXIT中会释放物理页)

4.voidFork(void(*func)())

1)从4号寄存器中读出要执行的用户函数的起始PC

2)新创建一个线程,并参照Exec中的步骤,完成父子关系的建立

3)PC前移。

4)在Fork的系统函数中,完成准备工作:

将父进程的用户空间(Pagetable)拷贝到子进程中;

将machine当前的PC值修改为1)中的PC值,NextPC值修改为1)中的PC值+4;

将修改完成的这套寄存器值存放到新

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 法律资料

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1