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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

GeekOS操作系统课程设计报告完美版.docx

1、GeekOS操作系统课程设计报告完美版编号: GeekOS操作系统的研究与实现 题 目:GeekOS操作系统的研究与实现系 别: 计算机科学与工程学院 专 业: 计算机科学与技术 学生姓名: 学 号: 指导教师: 注:高分操作系统课程设计报告,当初为我加了不少分哦!2012年3月171 实验目的计算机操作系统是管理计算机系统软件、硬件资源,控制程序运行,改善人机界面,提供各种服务,合理组织计算机工作流程和为用户有效使用计算机提供良好的运行环境的系统软件,它为用户使用计算机提供一个方便、灵活、安全、可靠的工作环境,也是其他应用软件赖以存在的基础。不仅是高校计算机专业学生需要了解它,从事计算机行业

2、的人员也需要深入了解它。由于目前高校开设的计算机操作系课程中偏重对理论知识的要求,实践环境有限,并偏重注重学生对一些经典算法的实践,学生并没有机会了解、实践操作系统的内部结构和实现技术。经过一个学期的操作系统理论学习,我们基本上掌握了操作系统的理论基础知识,但是,操作系统课程的内容不仅仅涉及理论、算法,更重要的是用技术去实现算法并对其加以实现和应用。 此次课程设计,通过搭建Linux实验平台,对专门为操作系统课程教学而设计的操作系统GeekOS的项目代码的补充和完善,从浅到深,由表面到内涵地去理解操作系统的设计思想,理解操作系统内核工作的基本原理。在完成项目的过程中,通过动手操作,使得我们能够

3、在动手查阅资料、思考排难等探索性活动中进一步理解操作系统的抽象概念,并进一步理解操作系统复杂的结构和工作原理。 具体的来说,对于项目0,应该熟悉GeekOS的项目编译,调试和运行环境,掌握GeekOS的运行工作过程;对于项目1,应该熟悉ELF文件格式,了解GeekSO系统如何将ELF格式的用户可执行程序装入到内存,建立内核进程并运行的实现技术;对于项目2,扩充GeekOS操作系统内核,使得系统能够支持用户级进程的动态创建和执行。2 项目的设计要求2.1 Project0项目设计要求(1) 搭建GeekOS的编译和调试平台,掌握GeekOS的内核进程工作原理。(2) 熟悉键盘操作函数,编程实现一

4、个内核进程。该进程的功能是:接受键盘输入的字符并显示在屏幕上,当按ctrl+D时,结束进程的运行。2.2 Project1项目设计要求1、修改/geekos/elf.c文件:在函数Parse_ELF_Executable( )中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度,代码段、数据段等信息),并填充Exe_Format数据结构中的域值。2、在Linux环境下编译系统得到GeekOS镜像文件。3、编写一个相应的bochs配置文件。4、在bochs中运行GeekOS系统显示结果。2.3 Project2项目设计要求项目2要求用户对以下几个文件进行修

5、改:1)“src/GeekOS/user.c”文件中的函数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()函数的功能是释放用户

6、态进程占用的内存资源。 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函数。 S

7、etup_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_Wait(

8、)函数和Sys_GetPID( )函数。7)在main.c文件中改写生成第一个用户态进程的函数调用:Spawn_Init_Process(void) 。3 开发环境的建立3.1 在虚拟机上安装Linux操作系统GeekOS是一个基于X86架构的PC机上运行的微操作系统内核,内核简单却又兼备实用性,是一个用C语言开发的操作系统,可以运行在真正的X86PC硬件平台。每个项目需要在Linux环或者UNIX环境下对其进行功能扩充。Ubuntu 是一个由社区开发的基于linux的操作系统,其包含了我们一般所需的所有程序:无论是文字处理和电子邮件,还是 Web 服务和编程工具。所以选择其作为Linux系统

9、进行安装。首先先安装VMware workstation,运行Vmware,新建一个虚拟机,以便安装Linux系统。然后在虚拟机上安装Ubuntu系统。系统安装的时候会默认安装了GCC,所以后面不必再重新安装GCC。3.2 安装c/c+编译环境(1)修改使用国内镜像更新源。在命令行终端中输入sudo gedit /etc/apt/sources.list,打开“文本编辑器编辑源列表”。在最后一行添加下列国内镜像更新源:deb-src jaunty-updates main multiverse restricted universe 保存,即可。(2)终端中输入sudo apt-get upd

10、ate 重新获取软件包列表。(3)在终端输入 sudo apt-get intall build-essential 下载安装 build-essential包。(4)安装NASM在终端执行udo apt-get install nasm,(5)安装Bochs:在终端执行 sudo apt-get install bochs在终端执行 sudo apt-get install bochs-x4 项目设计原理4.1 Project0设计原理利用GeekOS提供的键盘处理函数keyboard.h与keyboard.c等进行键盘常用功能的模拟。其中,在keyboard.c里面提供了一个功用函数Key

11、code Wait_For_Key(void),循环等待一个键盘事件,然后返回一个16位的数据 Keycode型的, 在keyboard.h里定义了所有的键盘代码。Read_Key(Keycode* keycode)函数可以处理队列键盘按键,可以保存到队列中并输出。另外,需要重点关Start_Kernel_Thread函数。函数的参数startFunc是一个Thread_Start_Func类型的函数指针,其定义在kthread.h中:Typedef void (*Thread_Start_Func) (ulong_t,arg);该函数指针指向一个无返回值,参数为ulong_t类型的函数。函数

12、的功能是以参数Start_Func指向的代码为进程体生成一个内核进程。再有,对于Read_Key()函数,其定义为:bool Read_Key(Keycode *keycode);作用是轮查键盘事,如果捕获到键盘事件,则返回true,并且将按键码保存到参数 keycode地址中。4.2 Project1设计原理 ELF(Executable and linking format)文件是UNIX系统实验室作为应用程序二进制接口而开发的可执行文件,是x86 Linux系统下的一种常用目标文件(object file)格式。ELF文件格式如下表1。表1 ELF目标文件格式连接程序视图 执行程序视图

13、ELF 头部ELF 头部 程序头部表(可选) 程序头部表 节区1 段 1 . 节区 n 段 2 . . . 节区头部表 节区头部表(可选) ELF文件在磁盘中的映象和在内存中的执行程序镜像的对应关系如下图:图1 ELF文件和内存中的可执行文件镜像内核进程的创建流程如下图:图2 内核进程流程图Parse_ELF_Excutable函数的定义为:int Parse_ELF_Executable(char *exeFileData,ulong_t exeFileLength,truct Exe_Format *exeFormat)参数:exeFileData已装入内存的可执行文件所占用空间的起始地址

14、 exeFileLength可执行文件长度 exeFormat保存分析得到的elf文件信息的结构体指针根据ELF文件格式,用户可以从exeFileData指向的内容中得到ELF文件头,继续分析可以得到程序头,程序代码段等信息。4.3 Project2设计原理Geekos进程状态及转化: 图3 GeekOS进程状态转换GeekOS系统最早创建的内核进程有Idle、Reaper和Main三个进程,它们由Init_Scheduler函数创建:最先初始化一个核态进程mainThread,并将该进程作为当前运行进程,函数最后还调用Start_Kernel_Thread 函数创建了两个系统进程Idle和R

15、eaper。 所以,Idle、Reaper和Main三个进程是系统中最早存在的进程。在GeekOS中为了区分用户态进程和内核进程,在Kernel_Thread结构体中设置了一个字段 userContext,指向用户态进程上下文。对于内核进程来说,这个指针为空,而用户态进程都拥有自己的用户上下文(User_Context)。因此,在GeekOS中要判断一个进程是内核进程还是用户态进程,只要通过userContext字段是否为空来判断就可以了。每个用户态进程都拥有属于自己的内存段空间,如:代码段、数据段、堆栈段等,每个段有一个段描述符(segment descriptor),并且每个进程有一个段描

16、述符表(Local Descriptor Table),用于保存该进程的所有段描述符。操作系统中还设置一个全局描述符表(GDT,Global Descriptor Table),用于记录了系统中所有进程的ldt描述符。图10.2 GDT、LDT和User_Context的关系用户态进程创建LDT的步骤:(1)调用函数Allocate_Segment_Descriptor()新建一个LDT描述符;(2)调用函数Selector()新建一个LDT选择子;(3)调用函数Init_Code_Segment_Descriptor()新建一个文本段描述符;(4)调用函数Init_Data_Segment_

17、Descriptor()新建一个数据段;(5)调用函数Selector()新建一个数据段选择子;(6)调用函数Selector()新建一个文本(可执行代码)段选择子。用户态进程创建流程:5 项目设计的具体实现5.1 Project0项目的具体实现在project/project0/src/geekos/main.c中添加一个函数。函数的功能是:接收键盘输入的按键,并将键值显示到显示器的函数,当输入Ctrl+D就退出。函数代码如下:= main.c=void project0() Print(To Exit hit Ctrl + d.n); Keycode keycode; while(1) i

18、f( Read_Key(&keycode) ) /读取键盘按键状态 if(!( (keycode & KEY_SPECIAL_FLAG) | (keycode & KEY_RELEASE_FLAG) ) /只处理非特殊按键的按下事件 int asciiCode = keycode & 0xff; /低8位为Ascii码 if( (keycode & KEY_CTRL_FLAG)=KEY_CTRL_FLAG & asciiCode=d) /按下Ctrl键 Print(n-BYE!-n); Exit(1); else Print(%c,(asciiCode=r) ? n : asciiCode);

19、 = (2) 首先注释Main()函数中TODO宏,并调用Start_Kernel_Thread函数,将步骤1编写的函数地址传递给参数,建立一个内核级进程 struct Kernel_Thread *thread; thread = Start_Kernel_Thread(&project0,0,PRIORITY_NORMAL,false);(3) 执行make depend及make命令,此时会在build目录下生成fd.img(4) 编写brochs 配置文件vgaromimage: file=/usr/share/bochs/VGABIOS-lgpl-latestromimage: fi

20、le=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000megs: 8boot: afloppya: 1_44=fd.img, status=inserted#floppya: 1_44=fd_aug.img, status=insertedlog: ./bochs.outkeyboard_serial_delay: 200floppy_command_delay: 500vga_update_interval: 300000ips: 1000000mouse: enabled=0private_colormap: enabled=0i440

21、fxsupport: enabled=05.2 Project1项目的具体实现修改project/project1/src/geekos/elf.c文件:在函数Parse_ELF_Executable( )中添加代码,分析 ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文 件长度,代码段、数据段等信息),并填充Exe_Format数据结构中的域值1、elf.c:将ELF格式的可执行程序装入到内存,建立内核进程并运行.= elf.c = int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, st

22、ruct Exe_Format *exeFormat) int i; elfHeader *head=(elfHeader*)exeFileData; programHeader *proHeader=(programHeader *)(exeFileData+head-phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLengthhead-ehsize+head-phentsize*head-phnum); KASSERT(head-entry%4=0); exeFormat-numSegments=head-phnum; exeForma

23、t-entryAddr=head-entry; for(i=0;iphnum;i+) exeFormat-segmentListi.offsetInFile=proHeader-offset; exeFormat-segmentListi.lengthInFile=proHeader-fileSize; exeFormat-segmentListi.startAddress=proHeader-vaddr; exeFormat-segmentListi.sizeInMemory=proHeader-memSize; exeFormat-segmentListi.protFlags=proHea

24、der-flags; proHeader+;return 0;=2、编译,成功后生成两个镜像文件:fd.img和diskc.img。其中,Diskc.img为模拟器能引导的操作系统镜像 。 3、编写相应的bochs配置文件 由于生成了diskc.img,因此配置文件需加上以下内容config_interface: textconfigmegs: 8vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latestromimage: file=$BXSHARE/BIOS-bochs-latestfloppya: 1_44=./fd.img, status=inserte

25、data0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14ata1: enabled=0, ioaddr1=0x170, ioaddr2=0x370, irq=15#ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11#ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9ata0-master: type=disk, path=diskc.img, mode=flat, cylinders=40, heads=8, spt=64#ata0-

26、slave: type=cdrom, path=/dev/cdrom, status=insertedboot: aips: 1000000log:./bochs.outvga_update_interval: 300000keyboard_serial_delay: 250keyboard_paste_delay: 100000private_colormap: enabled=0 5.3 Project2项目的具体实现1、添加代码= user.c =/产生一个进程(用户态)int Spawn(const char *program, const char *command, struct

27、Kernel_Thread *pThread) /TODO(Spawn a process by reading an executable from a filesystem); int rc; /标记各函数的返回值,为0则表示成功,否则失败 char *exeFileData = 0;/保存在内存缓冲中的用户程序可执行文件 ulong_t exeFileLength;/可执行文件的长度 struct User_Context *userContext = 0;/指向User_Conetxt的指针 struct Kernel_Thread *process = 0;/指向Kernel_Thr

28、ead *pThread的指针 struct Exe_Format exeFormat;/调用Parse_ELF_Executable函数得到的可执行文件信息 if (rc = Read_Fully(program, (void*) &exeFileData, &exeFileLength) != 0 ) /调用Read_Fully函数将名为program的可执行文件全部读入内存缓冲区 Print(Failed to Read File %s!n, program); goto fail; if(rc = Parse_ELF_Executable(exeFileData, exeFileLen

29、gth, &exeFormat) != 0 ) /调用Parse_ELF_Executable函数分析ELF格式文件 Print(Failed to Parse ELF File!n); goto fail; if(rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext) != 0) /调用Load_User_Program将可执行程序的程序段和数据段装入内存 Print(Failed to Load User Program!n); goto fail; /在堆分配方式下释放内存

30、并再次初始化exeFileData Free(exeFileData); exeFileData = 0;/* 开始用户进程,调用Start_User_Thread函数创建一个进程并使其进入准备运行队列*/ process = Start_User_Thread(userContext, false); if (process != 0) /不是核心级进程(即为用户级进程) KASSERT(process-refCount = 2);/* 返回核心进程的指针 */ *pThread = process; rc = process-pid;/记录当前进程的ID else/超出内存 project2includegeekoserrno.h rc = ENOMEM; return rc;fail: /如果新进程创建失败则注

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

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