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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

操作系统课程设计75303.docx

1、操作系统课程设计75303 课程设计说明书学 院: 计算机科学与工程学院 专 业: 计算机科学与技术 姓 名: 天驹 学 号: 0900310327 指导教师: 黄廷辉 2012年 3 月 5 日操作系统课程设计报告GeekOS操作系统的研究与实现(项目0-项目2)一、 实验目的:熟悉GeekOS项目编译运行环境、核态进程的实现、用户态进程的实现、进程调度策略和算法实现、分页存储管理的实现和文件系统的实现等。二、 项目设计要求:GeekOS设计项目0:1. 搭建GeekOS的编译和调试平台,掌握GeekOS的核进程工作原理。2. 熟悉键盘操作函数,编程实现一个核进程。该进程的功能是:接受键盘输

2、入的字符并显示到屏幕上,当输入Ctrl+D时,结束进程的运行。GeekOS设计项目1:1.修改/geekos/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长度、代码段、数据段等信息),并填充Exe_Format数据结构中的域值。2.掌握GeekOS在核心态运行用户程序的原理,为项目2的实现做准备。GeekOS设计项目2:本项目要求用户对以下几个文件进行修改:1. src/GeekOS/user.c文件中的函数Spawn(),其功能是生成一个新的用户级进程。2. src/GeekOS/u

3、sre.c文件中的函数Switch_To_User_Context(),调度程序在执行一个新的进程前调用该函数以切换用户地址空间。3. src/GeekOS/elf.c文件中的函数Parse_ELF_Executable()。该函数的实现要求和项目1相同。4. src/GeekOS/userseg.c文件中主要是实现一些为实现对src/GeekOS/user.c中高层操作支持的函数。 (1)Destroy_User_Context()函数的功能是释放用户态进程占用的存资源。 (2)Load_User_Program()函数的功能是通过加载可执行文件镜像创建新进程的User_Context结构。

4、 (3)Copy_From_User()和Copy_To_User()函数的功能是在用户地址空间和核地址空间之间复制函数,在分段存储器管理模式下,只要段有效,调用memcpy函数就可以实现这两个函数的功能。 (4)Switch_To_Address_Space()函数的功能是通过将进程的LDT装入到LDT寄存器来激活用户的地址空间。5. src/GeekOS/kthread.c文件中的Start_User_Thread函数和Setup_User_Thread函数。 (1)Setup_User_Thread()函数的功能是为进程初始化核堆栈,堆栈中是为进程首次进入用户态运行时设置处理器状态要使用

5、的数据。 (2)Start_User_Thread()是一个高层操作,该函数使用User_Context对象开始一个新进程 6. src/GeekOS/Syscall.c文件中主要是实现用户程序要求核进行服务的一些系统调用函数定义。要求用户实现的有Sys_Exit()函数、Sys_PrintString()函数、Sys_GetKey()、Sys_SetAttr()、Sys_Getcursor()、Sys_PutCursor()函数、Sys_Wait()函数和Sys_GetPID()函数。这些函数在文件中有详细的注释,按照提示用户可以很好实现它们的功能。 最后,需要在main.c文件中改写生成第

6、一个用户态进程的函数调用:Spawn_Init_Process(void)。需要注意的是:作为与用户沟通的界面,GeekOS提供了一个简单的Shell,保存在PFAT文件系统,所以GeekOS系统启动后,应启动shell程序/c/shell.exe运行,所以需要将/c/shell.exe作为可执行文件传递给Spawn函数的program参数,创建第一个用户态进程,然后由它来创建其他进程。 添加代码运行成功后,GeekOS就可以挂载shell,并能运行测试文件c.exe和b.exe。三、 如何建立开发环境:(一) 利用linux安装盘安装了ubuntu10.10版本的linux操作系统环境;(二

7、) 联网后通过系统里的更新管理器更新了系统,并安装了语言包和必要的驱动。(三) 在ubuntu软件中心下载安装了NASM汇编器、Bochs PC模拟器以及bochs-x插件(保证ubuntu10.10环境下的bochs正常运行)。四、 项目设计原理: Make工作原理:在默认的方式下,只要输入make命令就可以工作。具体的处理过程如下:(1)make会在当前目录下找文件名为“Makefile”或“makefile”的文件。 (2)如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,它会找到“edit”这个文件,并把这个文件作为最终的目标文件。 (3)如果edit文件不存在,

8、或是edit所依赖的后面的.o文件的修改时间要比edit这个文件新,那么,就会执行后面所定义的命令来生成edit这个文件。 (4)如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件(这有点像一个堆栈的过程)。 (5)如果指定的C文件和H文件是存在的, make会生成.o文件,然后再用.o文件生成make的最终任务,也就是生成执行文件edit。 GeekOS的makefile文件功能:(1) 指定GeekOS如何被编译,哪些源文件被编译,哪些用户程序被编译等等。通常不同项目的编译仅仅需要修改这一部分。(2) 定义了编译

9、GeekOS要用到的工具程序。(3) 指定规则:描述系统如何编译源程序。(4) 指定系统编译生成的指定文件 。GeekOS项目的开发流程:1. 开始一个GeekOS项目,第一步是添加相应的代码 。2. 在Linux下利用make命令编译系统,生成系统镜像文件。1 $ cd /project0/build2 $ make depend3 $ make 3. 编写每个项目相应的Bochs的配置文件。4. 运行Bochs模拟器,执行GeekOS核。1 $ cd /bochs 2 $ bochs 3 运行后,屏幕上会有一些提示。运行GeekOS选择Begin simulation,如果GeekOS 编

10、译成功,并且bochs的配置也没问题,将会看到一个模拟VGA的文本窗口,Geekos就能运行程序输出相应信息 (每个环境具体运行的命令格式会有一些不同)核线程的建立流程: 用户态进程创建流程 五、 项目设计的具体实现(程序代码):GeekOS设计项目0:Main.c文件:#include #include #include #include #include #include #include #include #include #include #include /* * Kernel C code entry point. * Initializes kernel subsystems,

11、mounts filesystems, * and spawns init process. */void Main(struct Boot_Info* bootInfo) Init_BSS(); Init_Screen(); Init_Mem(bootInfo); Init_CRC32(); Init_TSS(); Init_Interrupts(); Init_Scheduler(); Init_Traps(); Init_Timer(); Init_Keyboard(); Set_Current_Attr(ATTRIB(BLACK, GREEN|BRIGHT); Print(Welcom

12、e to GeekOS!n); Set_Current_Attr(ATTRIB(BLACK, GRAY); void EchoCount() Keycode keycode; int count; count=0; while (1) if ( Read_Key( &keycode ) ) if(keycode & 0x4000) = 0x4000) if(Wait_For_Key() & 0x00ff) = d) /Print(%c,Wait_For_Key(); Set_Current_Attr(ATTRIB(BLACK, RED); Print(Ctrl+d Is Entered! Pr

13、ogram 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(ATTRIB(AMBER, BLUE); Print(The counnts is %d

14、 ,count); Print(n); count=0; struct Kernel_Thread *kerThd;kerThd = Start_Kernel_Thread(&EchoCount, 0 , PRIORITY_NORMAL, false); /* Now this thread is done. */ Exit(0);GeekOS设计项目1:Elf.c文件:#include #include #include #include /* for debug Print() statements */#include #include #include #include /* * Fr

15、om the data of an ELF executable, determine how its segments * need to be loaded into memory. * param exeFileData buffer containing the executable file * param exeFileLength length of the executable file in bytes * param exeFormat structure describing the executables segments * and entry address; to

16、 be filled in * return 0 if successful, phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLengthhead-ehsize+head-phentsize*head-phnum); KASSERT(head-entry%4=0); exeFormat-numSegments=head-phnum; exeFormat-entryAddr=head-entry; for(i=0;iphnum;i+) exeFormat-segmentListi.offsetInFile=proHeader-offset;

17、 exeFormat-segmentListi.lengthInFile=proHeader-fileSize; exeFormat-segmentListi.startAddress=proHeader-vaddr; exeFormat-segmentListi.sizeInMemory=proHeader-memSize; exeFormat-segmentListi.protFlags=proHeader-flags; proHeader+;return 0;GeekOS设计项目2:Src/GeekOS/user.c文件中的函数Spawn():int Spawn(const char *

18、program, const char *command, struct Kernel_Thread *pThread) /* * Hints: * - Call Read_Fully() to load the entire executable into a memory buffer * - Call Parse_ELF_Executable() to verify that the executable is * valid, and to populate an Exe_Format data structure describing * how the executable sho

19、uld be loaded * - Call Load_User_Program() to create a User_Context with the loaded * program * - Call Start_User_Thread() with the new User_Context * * If all goes well, store the pointer to the new thread in * pThread and return 0. Otherwise, return an error code. */ int rc; char *exeFileData = 0;

20、 ulong_t exeFileLength; struct User_Context *userContext = 0; struct Kernel_Thread *process = 0; struct Exe_Format exeFormat; /* * Load the executable file data, parse ELF headers, * and load code and data segments into user memory. */ if (rc = Read_Fully(program, (void*) &exeFileData, &exeFileLengt

21、h) != 0 | (rc = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat) != 0 | (rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext) != 0) goto fail; /* * User program has been loaded, so we can free the * executable file data now. */ Free(exeFileData); exeFileD

22、ata = 0; /* Start the process! */ process = Start_User_Thread(userContext, false); if (process != 0) KASSERT(process-refCount = 2); /* Return Kernel_Thread pointer */ *pThread = process; else rc = ENOMEM; return rc;fail: if (exeFileData != 0) Free(exeFileData); if (userContext != 0) Destroy_User_Con

23、text(userContext); return rc;Src/GeekOS/user.c文件中的函数Switch_To_User_Context():void Switch_To_User_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state) /* * Hint: Before executing in user mode, you will need to call * the Set_Kernel_Stack_Pointer() and Switch_To_Address_Space() * func

24、tions. */ static struct User_Context* s_currentUserContext; /* last user context used */ struct User_Context* userContext = kthread-userContext; /* * FIXME: could avoid resetting ss0/esp0 if not returning * to user space. */ KASSERT(!Interrupts_Enabled(); if (userContext = 0) /* Kernel mode thread:

25、no need to switch address space. */ return; /* Switch only if the user context is indeed different */ if (userContext != s_currentUserContext) ulong_t esp0; /* Switch to address space of user context */ Switch_To_Address_Space(userContext); /* * By definition, when returning to user mode there is no

26、 * context remaining on the kernel stack. */ esp0 = (ulong_t) kthread-stackPage) + PAGE_SIZE; /* Change to the kernel stack of the new process. */ Set_Kernel_Stack_Pointer(esp0); /* New user context is active */ s_currentUserContext = userContext; src/GeekOS/elf.c文件中的函数Parse_ELF_Executable():int Par

27、se_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat) elfHeader *hdr; programHeader *phdr; int i; hdr = (elfHeader *) exeFileData; /* * FIXME: when checking offsets, we really ought to be * checking overflow cases. Need to use functions from * range.h (which needs

28、 to be implemented, too) */ if (exeFileLength phnum EXE_MAX_SEGMENTS) if (elfDebug) Print(Too many segments (%d) in ELF executablen, hdr-phnum); return ENOEXEC; if (exeFileLength phoff + (hdr-phnum * sizeof(programHeader) if (elfDebug) Print(Not enough room for program headern); return ENOEXEC; exeFormat-numSegments = hdr-phnum; exeFormat-entryAdd

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

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