nachosLab6实习报告DOC.docx

上传人:b****7 文档编号:9668325 上传时间:2023-02-05 格式:DOCX 页数:20 大小:411.02KB
下载 相关 举报
nachosLab6实习报告DOC.docx_第1页
第1页 / 共20页
nachosLab6实习报告DOC.docx_第2页
第2页 / 共20页
nachosLab6实习报告DOC.docx_第3页
第3页 / 共20页
nachosLab6实习报告DOC.docx_第4页
第4页 / 共20页
nachosLab6实习报告DOC.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

nachosLab6实习报告DOC.docx

《nachosLab6实习报告DOC.docx》由会员分享,可在线阅读,更多相关《nachosLab6实习报告DOC.docx(20页珍藏版)》请在冰豆网上搜索。

nachosLab6实习报告DOC.docx

nachosLab6实习报告DOC

系统调用实习报告

目录

内容一:

总体概述3

内容二:

任务完成情况3

任务完成列表(Y/N)3

具体Exercise的完成情况3

内容三:

遇到的困难以及解决方法16

内容四:

收获及感想16

内容五:

对课程的意见和建议16

内容六:

参考文献16

内容一:

总体概述

本次lab的主要内容是实现nachos定义的系统调用。

理论方面,我们需要了解nachos系统调用的实现原理,实践方面,我们需要实现文进系统相关系统调用和用户程序相关系统调用,并且编写用户程序验证相关系统调用的正确性。

内容二:

任务完成情况

任务完成列表(Y/N)

Exercise1

Exercise2

Exercise3

Exercise4

Exercise5

Y

Y

Y

Y

Y

具体Exercise的完成情况

一、理解Nachos系统调用

Exercise1源代码阅读

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

code/userprog/syscall.h

code/userprog/exception.cc

code/test/start.s

userprog/syscall.h定义nachos的系统调用,主要包括系统调用号和系统调用函数,内核通过识别用户程序传递的系统调用号确定系统调用类型

已经实现的系统调用包括

voidHalt();

关闭nachos虚拟机,打印性能统计信息

需要实现的系统调用包括:

3种系统调用涉及地址空间:

1)、voidExit(intstatus);

用户程序完成,status=0表示正常退出2)、SpaceIdExec(char*name);加载并执行名字是name的Nachos可执行文件,返回其地址空间的标志符

SpaceId实际是整型,标识地址空间

3)、intJoin(SpaceIdid);

等待标志符为id的用户线程运行完毕,返回其退出状态

5种系统调用涉及文件系统:

1)、voidCreate(char*name);创建文件名name的Nachos文件

2)、OpenFileIdOpen(char*name);打开文件名name的Nachos文件,返回打开文件标志符

OpenFileId实际是整形,标识打开文件

3)、voidWrite(char*buffer,intsize,OpenFileIdid);向标志符是id的文件写入buffer中长度为size字节的数据

4)、intRead(char*buffer,intsize,OpenFileIdid);从标志符是id的文件读取长度为size字节的数据存入buffer,返回实际读取的字节数

5)、voidClose(OpenFileIdid);关闭标志符是id的文件

2种系统调用涉及用户级线程,用于支持多线程用户程序:

1)、voidFork(void(*func)());创建和当前线程拥有相同地址空间的线程,运行func指针指向的函数

2)、voidYield();

当前线程让出CPU

code/userprog/exception.cc定义进行异常处理的ExceptionHandler函数,主要流程是根据异常信息处理不同异常,包括系统调用

目前支持的异常:

NoException,//正常

SyscallException,//系统调用

PageFaultException,//缺页(页表/快表)

ReadOnlyException,//访问只读页面

BusErrorException,//总线错误

AddressErrorException,//访问地址对齐错误/超出范围

OverflowException,//算数溢出

IllegalInstrException,//非法指令

NumExceptionTypes

处理系统调用时,需要从2号寄存器获得系统调用号确定系统调用类型

code/test/start.s是辅助用户程序运行的汇编代码,主要包括初始化用户程序和系统调用相关操作

(1)初始化用户程序:

通过调用main函数运行用户程序

.globl__start

.ent__start

__start:

jalmain//跳转到main函数执行用户程序

move$4,$0//main函数返回

//r4寄存器存入0,作为下面调用Exit参数

jalExit

.end__start

(2)系统调用:

用户程序执行系统调用时,将系统调用号存入r2寄存器,然后跳转到exception.cc执行,例如系统调用Halt:

Halt:

addiu$2,$0,SC_Halt//将系统调用号存入r2寄存器

syscall

j$31

.endHalt

系统调用相关寄存器:

r2->系统调用号,系统调用返回值

r4->系统调用参数1

r5->系统调用参数2

r6->系统调用参数3

r7->系统调用参数4

系统调用主要流程:

machine的Run函数运行用户程序,实现在machine/mipssim.cc,基本流程是通过OneInstruction函数完成指令译码和执行,通过interrupt的OneTick函数使得时钟前进

(1)OneInstruction函数判断当前指令是系统调用,转入start.s

(2)通过start.s确定系统调用入口,通过寄存器r2传递系统调用号,转入exception.cc(此时系统调用参数位于相应寄存器)

(3)exception.cc通过系统调用号识别系统调用,进行相关处理,如果系统调用存在返回值,那么通过寄存器r2传递,流程结束时,需要更新PC

(4)系统调用结束,程序继续执行

添加系统调用:

(1)syscall.h定义系统调用接口、系统调用号

(2)code/test/start.s添加链接代码

(3)exception.cc添加系统调用处理过程

二、文件系统相关的系统调用

Exercise2系统调用实现

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

Create,Open,Close,Write,Read。

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

基本思路:

修改userprog/exception.cc,按照userprog/syscall.h的定义实现系统调用

系统调用Create定义

voidCreate(char*name);

系统调用Create基本流程

(1)通过寄存器r4获得文件名指针

(2)使用文件名指针通过已经实现ReadMem函数获得文件名

(3)通过已经实现的Create函数创建文件

(4)通过函数PC_advance更新PC

系统调用Open定义

OpenFileIdOpen(char*name);

系统调用Open基本流程

(1)通过寄存器r4获得文件名指针

(2)使用文件名指针通过已经实现ReadMem函数获得文件名

(3)通过已经实现的Open函数打开文件

(4)返回值(打开文件数据结构)写入寄存器r2

(5)通过函数PC_advance更新PC

系统调用Close定义

voidClose(OpenFileIdid);

系统调用Close基本流程

(1)通过寄存器r4获得打开文件数据结构

(2)通过打开文件数据结构析构函数关闭文件

(3)通过函数PC_advance更新PC

系统调用Read定义

intRead(char*buffer,intsize,OpenFileIdid);

系统调用Read基本流程

(1)通过寄存器r4获得缓冲区指针,通过寄存器r5获得数据长度,通过寄存器r6获得打开文件数据结构

(2)通过已经实现的Read函数读取文件相关内容,记录实际读出字节数

(3)通过已经实现的WriteMem函数将文件内容写入缓冲区

(4)返回值(实际读出字节数)写入寄存器r2

(5)通过函数PC_advance更新PC

系统调用Write定义

voidWrite(char*buffer,intsize,OpenFileIdid);

系统调用Write基本流程

(1)通过寄存器r4获得缓冲区指针,通过寄存器r5获得数据长度,通过寄存器r6获得打开文件数据结构

(2)通过已经实现的ReadMem函数获得缓冲区数据

(3)通过已经实现的Write函数将缓冲区内容写入文件

(4)通过函数PC_advance更新PC

 

Exercise3编写用户程序

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

用户程序基本思路

创建文件write.txt(系统调用Create)

打开文件read.txt(已经存在,内容hello_world)(系统调用Open)

打开文件write.txt(系统调用Open)

读入文件read.txt内容,记录读入字节数(系统调用Read)

内容写入文件write.txt(系统调用Write)

关闭文件read.txt(系统调用Close)

关闭文件write.txt(系统调用Close)

用户程序的添加

修改test/MakeFile

all:

haltshellmatmultsorttest1

test1.o:

test1.c

$(CC)$(CFLAGS)-ctest1.c

test1:

test1.ostart.o

$(LD)$(LDFLAGS)start.otest1.o-otest1.coff

../bin/coff2nofftest1.cofftest1

用户程序的执行

检查userprog文件夹,出现文件write.txt

可以发现,相关内容顺利写入,符合实际

 

三、执行用户程序相关的系统调用

Exercise4系统调用实现

实现如下系统调用:

Exec,Fork,Yield,Join,Exit。

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

系统调用Exec定义

SpaceIdExec(char*name);

系统调用Exec基本流程

(1)通过寄存器r4获得文件名指针

(2)建立线程,通过函数exec_func执行用户程序

(3)返回值(线程ID)写入寄存器r2

(4)通过函数PC_advance更新PC

函数exec_func基本流程

(1)使用文件名指针通过已经实现ReadMem函数获得文件名

(2)通过已经实现的Open函数打开文件

(3)通过已经实现的AddrSpace的构造函数初始化地址空间

(4)通过已经实现的InitRegisters函数初始化寄存器

(5)通过已经实现的RestoreState函数装载页表

(6)通过已经实现的Run函数运行用户程序

重要部分可以仿照StartProcess函数实现

系统调用Fork定义

voidFork(void(*func)());

系统调用Fork基本流程

(1)通过寄存器r4获得函数位置

(2)复制当前进程地址空间

注意到AddrSpace的构造函数需要打开文件作为输入,所以增加线程属性,记录当前线程对应打开文件的名称,实现Fork函数时,需要逐页复制页表内容

(3)建立线程,执行函数fork_func

(4)通过函数PC_advance更新PC

函数Fork_func基本流程

(1)设置当前线程地址空间

(2)通过已经实现的InitRegisters函数初始化寄存器

(3)通过已经实现的RestoreState函数装载页表

(4)设置当前线程PC

(5)通过已经实现的Run函数运行用户程序

系统调用Yield定义

voidYield();

系统调用Yield基本流程

(1)通过函数PC_advance更新PC

(2)通过已经实现的Yield函数实现线程切换

这里需要先更新PC,否则陷入死循环

系统调用Join定义

intJoin(SpaceIdid);

系统调用Join基本流程

(1)通过寄存器r4获得线程ID

(2)检查全局数组ThreadID,确定特定线程是否处于活跃状态,如果特定线程处于活跃状态,那么进行线程切换

根据前面已经实现的机制,线程构造函数会分配线程ID,线程析构函数会回收线程ID,所以能够通过线程ID确定特定线程是否处于活跃状态

(3)通过函数PC_advance更新PC

系统调用Exit定义

voidExit(intstatus)

系统调用Exit基本流程

(1)通过寄存器r4获得退出状态,输出相关信息

(2)通过已经实现的clear函数释放页表相关空间

(3)通过函数PC_advance更新PC

(4)通过已经实现的Finish函数结束当前线程

 

Exercise5编写用户程序

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

用户程序1基本思路

(1)通过系统调用Exec执行特定文件

(2)通过系统调用Yield进行线程切换

涉及系统调用:

Exec、Yield、Exit

#include"syscall.h"

intmain()

{

Exec("halt");

Yield();

}

用户程序1执行结果

(1)主线程分配空间,开始执行

(2)执行系统调用Exec,建立新线程,准备执行halt

(3)执行系统调用Yield,主线程进行线程切换

(4)新线程分配地址空间,开始执行

(5)新线程执行完成,执行系统调用Exit,释放地址空间,输出相关信息

(6)主线程执行完成,执行系统调用Exit,释放地址空间,输出相关信息

结果如下,符合实际

用户程序2基本思路

(1)通过系统调用Exec执行特定文件

(2)通过系统调用Join等待新线程结束

涉及系统调用:

Exec、Join、Exit

#include"syscall.h"

intmain()

{

intid=Exec("halt");

Join(id);

}

用户程序2执行结果

(1)主线程分配空间,开始执行

(2)执行系统调用Exec,建立新线程,准备执行halt

(3)执行系统调用Join,新线程没有结束,主线程进行线程切换

(4)新线程分配地址空间,开始执行

(5)新线程执行完成,执行系统调用Exit,释放地址空间,输出相关信息

(6)主线程执行完成,执行系统调用Exit,释放地址空间,输出相关信息

结果如下,符合实际

用户程序3基本思路

(1)通过系统调用Fork建立新线程

(2)新线程执行相关操作

涉及系统调用:

Fork、Exit

#include"syscall.h"

voidfunc()

{

Create("test1.txt");

}

intmain()

{

Create("test2.txt");

Fork(func);

}

用户程序3执行结果

文件test1.txt,test2.txt顺利创建,符合实际

内容三:

遇到的困难以及解决方法

困难:

Fork系统调用的实现

Fork系统调用需要对页面进行深度复制,可以模仿AddrSpace构造函数的思路,逐字节复制相关页面。

我们可以发现,Fork的效率是比较低的,所以linux引入系统调用vfork和create解决这样的问题。

fork创造的子进程复制了父亲进程的所有资源,包括内存资源和task_struct内容。

vfork创造的子进程不是真正意义上的进程,而是线程,因为父进程和子进程共享内存资源,子进程缺少独立的内存资源,clone创造的子进程可以有选择性的继承父进程的资源。

内容四:

收获及感想

实习课程和理论课程相得益彰。

通过本次实习,我强化了对系统调用相关知识的理解,锻炼了编程能力。

经过本学期的学习,感觉对nachos系统有了初步的了解,对课程有了相当的兴趣,期待在以后的学习中能够更多的进行操作系统的相关实践

内容五:

对课程的意见和建议

我觉得课程形式好,互动强,使我受益匪浅。

我觉得课程形式好,互动强,使我受益匪浅。

助教认真负责,知识充分,为课程付出很多,助教辛苦了:

-D

内容六:

参考文献

[1]操作系统课件运行环境与运行机制

[2]nachos中文教程

[3]

Nachos3.4Lab2文件机制实习报告系统调用

[4]

Nachos系统调用实习报告

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

当前位置:首页 > 党团工作 > 入党转正申请

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

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