ImageVerifierCode 换一换
格式:DOCX , 页数:26 ,大小:761.82KB ,
资源ID:12850138      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12850138.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Geekos操作系统全部实验实现报告.docx)为本站会员(b****0)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Geekos操作系统全部实验实现报告.docx

1、Geekos操作系统全部实验实现报告计算机系统实验软件报告题目:Geekos操作系统的研究与实现(全部项目)院 (系): 计算机科学与工程学院 专 业: XXXXX 学生姓名: 周长劭 学 号: XXXXXXX 指导教师: 黄廷辉 2012年04月23日1 GeekOS简介GeekOS是一个基于X86架构的PC上运行的微操作系统内核。由美国马理兰大学的教师开发,是一个用C语言开发的操作系统。主要用于操作系统课程设计,目的是使学生能够实际动手参与到一个操作系统的开发工作中。出于教学目的,这个系统内核设计简单,却又兼备实用性,它可以运行在真正的X86 PC硬件平台。作为一个课程设计平台,GeekO

2、S由一个基本的操作系统内核作为基础,提供了操作系统与硬件之间的所有必备接口,实现了系统引导、实模式到保护模式的转换、中断调用及异常处理、基于段式的内存管理,FIFO进程调度算法以及内核进程、基本的输入输出(键盘作为输入设备、显示器作为输出设备),以及一个用于存放用户程序的只读文件系统PFAT。学生可以在Linux或Unix及Windows Cygwin环境下对其进行功能扩充,且其针对进程、文件系统、存储管理等操作系统核心内容分别设计了7个难度逐渐增加的项目供学生选择 11GeekOS系统源代码结构 GeekOS操作系统源文件geekos-.zip可以从下载。解压后的GeekOS目录结构如图1-

3、3所示:GeekOS系统的参考文档。Scripts目录下有startProject和removeEmptyConflicts两个脚本文件。GeekOS系统的源文件在src目录下,分为7个项目:Project0, Project1, Project2, Project3, Project4, Project5, Project6。每个项目的文件结构都类似,以Project0为例,结构如图1-4所示:在build文件夹中,包含系统编译后的可执行文件的文件、软盘镜像或是硬盘镜像、makefile项目管理文件。在inculde文件夹中有geekOS和libc两个子目录,在geekOS子目录中有kthr

4、ead.h,keyboard.h等头文件,在libc中包含有geekOS支持的C语言标准函数string.H头文件。在scripts文件夹是项目编译时要用到的一些脚本文件。Src文件夹中存放系统内核源代码,用户修改geekOS系统时要修改的源代码如main.c都位于这个目录中。在User子目录中一般是用来存放用户的测试文件,在tools子目录中的代码是用来建立PFAT测试文件系统的。2 实验环境1下载并完全安装Cygwin最新版2 Windows下配置Cygwin运行2Bochs最新版安装和使用3 项目实现31 Project0熟悉GeekOS的项目编译、调试和运行环境,掌握GeekOS运行工

5、作过程。项目设计要求(1)搭建GeekOS的编译和调试平台,掌握GeekOS的内核进程工作原理。(2)熟悉键盘操作函数,编程实现一个内核进程。该进程的功能是:接受键盘输入的字符并显示到屏幕上并计数,当输入Ctrl+D时,结束进程的运行。项目要求从键盘输入,因此要用到键盘处理函数 。GeekOS的键盘处理函数定义在keyboard.h与keyboard.c 文件中。键盘的初始化是在Main函数中调用Init_Keyboard进行的,Init_Keyboard主要功能是设置初始状态下存放键盘扫描码的缓冲区,并为键盘中断设置处理函数。而键盘中断处理过程是:首先从相应的I/O端口读取键盘扫描码,根据是

6、否按下Shift键,分别在键值表中寻找扫描码对应的按键值,经过处理后将键值放入键盘缓冲区,最后通知系统重新调度进程。若用户进程需要从键盘输入信息,可调用Wait_For_Key()函数,进程调用该函数后,会阻塞进入按键操作的等待队列,直到按键操作结束,进程才会被唤醒。Start_Kernel_Thread函数主要功能就是建立一个内核线程。本项目主要要求设计一个函数对键盘的中断进行响应。这主要通过使用Geekos提供的键盘响应函数Wait_For_Key()进行键盘中断的响应及返回键值。该函数首先检查键盘缓冲区是否有按键,如果有,就读取一个键码,如果此时键盘缓冲区中没有按键,就将线程放入键盘事件

7、等待队列。于是可分两步完成:1 编写函数EchoCount,函数功能是:接受键盘输入的按键,并将键值显示到显示器,当输入Ctrl+D退出。2 在Main函数体内调用Start_Kernel_Thread函数,将编写的函数地址传递给startFunc,建立一个内核进程。编写的函数svoid EchoCount() Keycode keycode; int count; count=0; while(1) if(Read_Key(&keycode) if(keycode & 0x4000) = 0x4000) if(Wait_For_Key() & 0x00ff) = d) Set_Current

8、_Attr(ATTRIB(BLACK, RED); Print(Ctrl+d Is Entered! Program Ended!); Exit(1); else if(!(keycode & KEY_SPECIAL_FLAG) & !(keycode & KEY_RELEASE_FLAG) keycode &= 0xff; count=count+1; Set_Current_Attr(ATTRIB(BLACK,CYAN); Print(%c,(keycode = r)?n:keycode); if(keycode=r) count=count-1; Set_Current_Attr(ATT

9、RIB(AMBER, BLUE); Print(The counnts is %d n ,count); count=0; 在mian函数中编写:Start_Kernel_Thread(keyin,0,PRIORITY_NORMAL,false);将编写的函数传入,生成内核进程。调试运行结果1.Windows里开始-运行:CMD,进入project0/build目录。 2.执行 make depend。3.执行make,成功之后在build 目录下生成fd.img文件。4.在build目录中启动执行bochs 。6.成功后,运行结果:32 Project13.21项目设计目的熟悉ELF文件格式

10、,了解GeekOS系统如何将ELF格式的用户可执行程序装入内存,建立内核进程并运行的实现技术。(1)修改/geekos/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度,代码段、数据段等信息),并填充Exe_Format数据结构的域值。(2)掌握GeekOS在核心态运行用户程序的原理,为项目2的实现做准备。3.23项目设计原理ELF是UNIX系统实验室作为应用程序二进制接口而开发和发布的。有两个平行视图。连接程序视图 执行程序视图 ELF 头部ELF 头部 程序头部表(可选) 程序头部

11、表 节区1 段 1 . 节区 n 段 2 . . . 节区头部表 节区头部表(可选) GeekOS中的用户程序全部在系统的编译阶段完成编译和连接,形成可执行文件,用户可执行文件保存在PFAT文件系统中。本项目要完成的就是在系统启动后,从PFAT文件系统将可执行文件装入内存,建立进程并运行得到相应的输出。在磁盘中的ELF文件的映像和在内存中执行程序镜像间的对应关系如下图所示而此过程主要由Spawner函数实现,其主要经过简要概述为:先调用Read_Fully函数将文件读入内存,后调用Parse_ELF_Executable函数分析ELF文件,最后调用Spawn_Program函数将可执行程序的代

12、码段和数据段等装入内存,此后便可以开始运行一个内核级进程了。如下图所示:在本项目中,我们要完成Parse_ELF_Executable函数,此函数的作用为根据ELF文件格式,从exeFileData指向的内容中得到ELF文件头,继续分析可得到程序头和程序代码段等信息。int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength,struct Exe_Format *exeFormat)elfHeader *eh = (elfHeader*)exeFileData; programHeader *ph=(programHead

13、er *)(exeFileData+eh-phoff);int i;for(i=0;iphnum;i+)exeFormat-segmentList i.offsetInFile=ph-offset;exeFormat-segmentList i.lengthInFile=ph-fileSize;exeFormat-segmentList i.startAddress=ph-vaddr;exeFormat-segmentList i.sizeInMemory=ph-memSize;exeFormat-segmentList i.protFlags=ph-flags; ph+;exeFormat-

14、numSegments=eh-phnum;exeFormat-entryAddr=eh-entry; return 0; 1.进入/os/ project1/build目录。 2.同上项目,文件。3.启动bochs 成功后,运行结果:33 Project23.31项目设计目的扩充GeekOS操作系统内核,使得系统能够支持用户级进程的动态创建和执行。开始本项目前需要阅读/src/geekos目录中的entry.c、lowlevel.asm、kthread.c、userseg.c,其中在userseg.c中主要关注Destroy_User_Context()和Load_User_Program()

15、两个函数。本项目要求用户对以下几个文件进行修改:1)”文件中的函数Spawn(),其功能是生成一个新的用户级进程;2)“src/GeekOS/user.c”文件中的函数Switch_To_User_Context(),调度程序在执行一个新的进程前调用该函数以切换用户地址空间;3)“src/GeekOS/elf.c”文件中的函数Parse_ELF_Executable()。该函数的实现要求和项目1相同。4)“src/GeekOS/userseg.c”文件中主要是实现一些为实现对“src/GeekOS/user.c”中高层操作支持的函数。 Destroy_User_Context()函数的功能是释

16、放用户态进程占用的内存资源。 Load_User_Program()函数的功能通过加载可执行文件镜像创建新进程的User_Context结构。 Copy_From_User()和Copy_To_User()函数的功能是在用户地址空间和内核地址空间之间复制数据,在分段存储器管理模式下,只要段有效,调用memcpy函数就可以实现这两个函数的功能。 Switch_To_Address_Space()函数的功能是通过将进程的LDT装入到LDT寄存器来激活用户的地址空间;5)“src/GeekOS/kthread.c”文件中的Start_User_Thread函数和Setup_User_Thread函数

17、。 Setup_User_Thread()函数的功能是为进程初始化内核堆栈,堆栈中是为进程首次进入用户态运行时设置处理器状态要使用的数据。 Start_User_Thread()是一个高层操作,该函数使用User_Context对象开始一个新进程。6)“src/GeekOS/kthread.c”文件中主要是实现用户程序要求内核进行服务的一些系统调用函数定义。要求用户实现的有Sys_Exit()函数、Sys_PrintString()函数、Sys_GetKey()、Sys_SetAttr()、Sys_GetCursor()、Sys_PutCursor()、Sys_Spawn()函数、Sys_Wa

18、it()函数和Sys_GetPID( )函数。7)在文件中改写生成第一个用户态进程的函数调用:Spawn_Init_Process(void) 。Geekos的初始系统不支持用户态进程,但提供了用户态进程上下文接口和实现用户态进程需要用到的数据结构。所以,用户态进程及相关函数都要开发者实现。在Geekos中为了区分用户态进程和内核进程,在Kernel_Thread结构体中设置了一个字段userContext,指向用户态进程上下文。对于内核进程来说,这个指针为空,而用户态进程都拥有自己的用户上下文。因此在Geekos中要判断一个进程是内核进程还是用户态进程,只要通过userContext字段是否

19、为空来判断就可以了。GeekOS的进程结构图如10-1所示:图10.1 用户态进程结构每个用户态进程都拥有属于自己的内存段空间,如:代码段、数据段、堆栈段等,每个段有一个段描述符(segment descriptor),并且每个进程有一个段描述符表(Local Descriptor Table),用于保存该进程的所有段描述符。操作系统中还设置一个全局描述符表(GDT,Global Descriptor Table),用于记录了系统中所有进程的ldt描述符。GDT、LDT和User_Context的关系如图10-2所示图10-2 GDT、LDT和User_Context的关系程序流程图:Geek

20、OS的用户级进程创建过程可以描述如下:(1)Spawn函数导入用户程序并初始化:调用Load_User_Program进行User_Context的初始化及用户级进程空间的分配及用户程序各段的装入;(2)Spawn函数调用Start_User_Thread(),初始化一个用户态进程,包括初始化进程Kernel_Thread结构以及调用Setup_User_Thread初始化用户级进程内核堆栈;(3)最后Spawn函数退出,这时用户级进程已被添加至系统运行进程队列,可以被调度了。3.33项目具体实现修改及增加的代码及函数如下(由于篇幅限制具体代码见附件):int Spawn(const char

21、 *program, const char *command, struct Kernel_Thread *pThread)void Switch_To_User_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state)int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength,struct Exe_Format *exeFormat)void Destroy_User_Context(struct User_Context* userCon

22、text)int Load_User_Program(char *exeFileData, ulong_t exeFileLength,struct Exe_Format *exeFormat, const char *command,struct User_Context *pUserContext)bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t bufSize)bool Copy_To_User(ulong_t destInUser, void* srcInKernel, ulong_t bufSize)

23、void Switch_To_Address_Space(struct User_Context *userContext)Start_User_Thread(struct User_Context* userContext, bool detached)void Setup_User_Thread(struct Kernel_Thread* kthread, struct User_Context* userContext)static int Sys_Exit(struct Interrupt_State* state)static int Sys_PrintString(struct I

24、nterrupt_State* state)static int Sys_GetKey(struct Interrupt_State* state)static int Sys_SetAttr(struct Interrupt_State* state)static int Sys_GetCursor(struct Interrupt_State* state)static int Sys_PutCursor(struct Interrupt_State* state)static int Sys_Spawn(struct Interrupt_State* state)static int S

25、ys_Wait(struct Interrupt_State* state)static int Sys_GetPID(struct Interrupt_State* state)3.34调试运行结果进入/os/ pp/project2/build目录,操作同上成功后,运行结果:34 Project33.41项目设计目的改进GeekOS的调度程序,实现基于4级反馈队列的调度算法(初始GeekOS系统仅提供了FIFO进程调度算法),并实现信号量,支持进程间通信。 (1)实现src/geekos/syscall.c文件中的Sys_SetSchedulingPolicy系统调用,它的功能是设置系统采

26、用的何种进程调度策略; (2)实现src/geekos/syscall.c文件中的Sys_GetTimeOfDay系统调用,它的功能是获取全局变量g_numTicks的值; (3)实现函数Change_Scheduling_Policy(),具体实现不同调度算法的转换。 (4)实现syscall.c中信号量有关的四个系统调用:sys_createsemaphore( )、sys_P( )、sys_V( )和sys_destroysemaphore( )。1)Set_Scheduling_Policy(policy,quantum),policy是设置的调度策略,quantum是设置的时间片。例

27、如policy为1说明设置的是多级反馈队列调度算法,g_schedulingPolicy设置为1(g_schedulingPolicy为系统添加的标识算法的变量,初始化为0)。如果policy为0,则说明设置的是轮转调度, g_schedulingPolicy设置为0,把4个队列变成一个队列,即所有的线程都在队列0上了。2)在系统调用Sys_GetTimeOfDay()中,只需要返回g_numTicks就可以了。在Sys_SetSchedulingPolicy()中,如果state-ebx是1,则设置的是MLF算法,为0则是RR算法。如果state-ebx为其他值,则返回-1。 3)在Init

28、_Thread()中都是把队列放在0队列上的,并且blocked变量为false。 4)在Get_Next_Runnable()中,从最高级的队列开始,调用Find_Best()来找线程优先级最大的线程,直到在某级队列中找到符合条件可以运行的线程。 5)在Wait()函数中,线程被阻塞,所以blocked变量被设置为true,并且如果是MLF算法,则该进程的currentReadyQueue加一,下次运行的时候进入高一级的线程队列。6)信号量定义 GveekOS定义了信号量的结构体:Struct Semaphore7)信号量PV操作 信号量操作:Semaphore_Create()Semaph

29、ore_Acquire(P操作)Semaphore_Release(V操作)Semaphore_Destroy()Semaphore_Create()函数首先检查请求创建的这个信号量的名字是否存在,如果存在,那么就把这个线程加入到这个信号量所注册的线程链表上;如果不存在,则分配内存给新的信号量,清空它的线程队列,把当前的这个线程加入到它的线程队列中,设置注册线程数量为1,初始化信号量的名字,值和信号量的ID,并把这个信号量添加到信号量链表上,最后返回信号量的ID。 P操作Semaphore_Acquire()中,首先检查传入的信号量ID是否存在,如果存在,接着检查当前线程是否注册使用了这个信号

30、量,如果这两项检查任意一项失败了,那么就返回-1。如果成功了,就把信号量的值减去1,如果减去1后信号量的值小于0,那么就把当前线程放入这个信号量的等待队列上。 V操作Semaphore_Release()中,首先也是检查传入的信号量ID是否存在,如果存在,接着检查当前线程是否注册使用了这个信号量,如果这两项检查任意一项失败了,那么就返回-1。如果成功了,那就把信号量的值加上1,如果加上1后信号量的值小于或等于0,则要把该信号量里等待队列上的一个线程唤醒。 Semaphore_Destroy()中,首先也是检查传入的信号量ID是否存在,如果存在,接着检查当前线程是否注册使用了这个信号量,如果这两

31、项检查任意一项失败了,那么就返回-1。如果成功了,就把该线程从这个信号量的注册的线程数组中删除,并把注册的线程数量减去1。如果这个信号量的注册线程为0了,则把这个信号量从信号量链表中删除,并释放它的内存。8)多级反馈队列调度队列模型 9)多级反馈队列与分时调度进程队列的转换struct Semaphore;DEFINE_LIST(Semaphore_List,Semaphore); struct Semaphore intsemaphoreID; char*semaphoreName; intvalue; intregisteredThreadCount; #defineMAX_REGISTERED_THREADS 60 structKernel_Thread *registeredThr

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

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