版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、课程设计说明书学 院:计算机科学与工程学院专业:计算机科学与技术姓名:杨天驹学 号: 07指导教师: 黄廷辉2012年3 月 5 日操作系统课程设计报告GeekOS操作系统的研究与实现(项目0项目2)一、实验目的:熟悉GeekOS项目编译运行环境、核态进程的实现、用户态进程的实现、 进程调度策略和算法实现、分页存储管理的实现和文件系统的实现等。二、项目设计要求:GeekOSg计项目0:1. 搭建GeekOS勺编译和调试平台,掌握 GeekOS勺内核进程工作原理。2. 熟悉键盘操作函数,编程实现一个内核进程。该进程的功能是:接受键盘 输入的字符并显示到屏幕上,当输入 Ctrl+D时,结束进程的运
2、行。GeekOSg计项目1:1. 修改/geekos/文件:在函数Parse_ELF_Executable()中添加代码,分析ELF 格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行文件长 度、代码段、数据段等信息),并填充Exe_Format数据结构中的域值。2. 掌握GeekOS在核心态运行用户程序的原理,审项目2的实现做准备。GeekOSS计项目2:本项目要求用户对以下几个文件进行修改:1. src/GeekOS/文件中的函数Spawn(),其功能是生成一个新的用户级进程。2. src/GeekOS/文件中的函数 Switch_To_User_Context(),调度程序在
3、执行 一个新的进程前调用该函数以切换用户地址空间。3. src/GeekOS/文件中的函数 Parse_ELF_Executable()。该函数的实现要求 和项目1相同。4. src/GeekOS/文件中主要是实现一些为实现对src/GeekOS/中高层操作支持的函数。(1) Destroy_User_Context()函数的功能是释放用户态进程占用的内存资源。一 一(2) Load_User_Program()函数的功能是通过加载可执行文件镜像创建 新进程的User_Context结构。(3) Copy_From_User()和 Copy_To_User()函数的功能是在用户地址空 间和内核
4、地址空间之间复制函数,在分段存储器管理模式下,只要段有效, 调用memcpy函数就可以实现这两个函数的功能。(4) Switch_To_Address_Space()函数的功能是通过将进程的 LDT装入 到LDT寄存器来激活用户的地址空间。5. src/GeekOS/ 文件中的 Start_User_Thread 函数和 Setup_User_Thread 函数。(1) Setup_User_Thread()函数的功能是为进程初始化内核堆栈,堆栈 中是为进程首次进入用户态运行时设置处理器状态要使用的数据。(2) Start_User_Thread() 是一个高层操作,该函数使用 User_C
5、on text 对象开始一个新进程6. src/GeekOS/ 文件中主要是实现用户程序要求内核进行服务的一些系统调 用函数定义。要求用户实现的有Sys_Exit()函数、Sys_PrintString()函数、Sys_GetKey() 、 Sys_SetAttr() 、 Sys_Getcursor() 、 Sys_PutCursor() 函数、 Sys_Wait()函数和Sys_GetPID()函数。这些函数在文件中有详细的注释, 按照提示用户可以很好实现它们的功能。最后, 需 要 在 文 件 中 改写生 成 第一 个 用 户 态 进程 的 函 数 调 用 : Spawn_Init_Proc
6、ess(void) 。需要注意的是:作为与用户沟通的界面, GeekOS 提供了一个简单的Shell,保存在PFAT文件系统内,所以GeekOS系统启动 后,应启动shell程序/c/运行,所以需要将/c/作为可执行文件传递给Spawn 函数的 program 参数,创建第一个用户态进程,然后由它来创建其他进程。添加代码运行成功后,GeekOS就可以挂载shell,并能运行测试文件和。三、如何建立开发环境:(一) 利用 linux 安装盘安装了版本的 linux 操作系统环境;(二) 联网后通过系统里的更新管理器更新了系统,并安装了语言包和必要的 驱动。(三) 在ubuntu软件中心下载安装了
7、 NASM汇编器、Bochs PC模拟器以及 bochs-x 插件(保证环境下的 bochs 正常运行)。四、项目设计原理:Make工作原理:在默认的方式下,只要输入 make命令就可以工作。具体的处理过程如下:(1) make会在当前目录下找文件名为“ Makefile ”或“ makefile ”的文件。(2) 如果找到,它会找文件中的第一个目标文件 (target ),在上面的例子中, 它会找到“ edit ”这个文件,并把这个文件作为最终的目标文件。(3) 如果 edit 文件不存在, 或是 edit 所依赖的后面的 .o 文件的修改时间要 比 edit 这个文件新,那么,就会执行后面
8、所定义的命令来生成 edit 这 个文件。(4) 如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标 为.0文件的依赖性,如果找到则再根据那一个规则生成.o文件(这有点 像一个堆栈的过程) 。(5) 如果指定的C文件和H文件是存在的,make会生成.0文件,然后再用.0文件生成make的最终任务,也就是链接生成执行文件edit。GeekOS的 makefile 文件功能:(1) 指定GeekOS如何被编译,哪些源文件被编译,哪些用户程序被编译 等等。通常不同项目的编译仅仅需要修改这一部分。(2) 定义了编译GeekOS要用到的工具程序。( 3) 指定规则:描述系统如何编译源
9、程序。(4) 指定系统编译生成的指定文件 。GeekOS项目的开发流程:1. 开始一个GeekOS项目,第一步是添加相应的代码。2. 在Linux下利用make命令编译系统,生成系统镜像文件。 $ cd /projectO/build $ make depend $ make3. 编写每个项目相应的Bochs的配置文件。4. 运行Bochs模拟器,执行GeekOS核。 $ cd /bochs $ bochs 运行后,屏幕上会有一些提示。运行GeekOS选择Beginsimulation ,如果GeekOS编译成功,并且bochs的配置也 没问题,将会看到一个模拟 VGA的文本窗口,Geekos
10、就能 运行程序输出相应信息(每个环境具体运行的命令格式会有一些不同)内核线程的建立流程:用户态进程创建流程Spawn ()ReadFully()Parse_ELF_Excti tab!le)1!_Laad_User_.Program ()1Start Usef Thread ()tSetup User Thread 0Attach_User_Context ()五、项目设计的具体实现(程序代码):GeekOS设计项目0:文件:#i nclude #i nclude #i nclude #i nclude #i nclude #i nclude #i nclude #i nclude #i nc
11、lude #include #include /* * Kernel C code entry point.* Initializes kernel subsystems, 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
12、();Init_Keyboard();Set_Current_Attr(ATTRIB(BLACK, GREEN|BRIGHT);Print(Welcome 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)*/Exit(0);GeekOSS计项目1:文件
13、:#include #include #include #include /* for debug Print() statements */#include #include #include #include /* From 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 exe
14、cutable file in bytes* param exeFormat structure describing the executables segments* and entry address; to 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;exe
15、Format-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-segmentLtFlags=proHead
16、er-flags;proHeader+; return 0;GeekOSS计项目2:Src/GeekOS/文件中的函数 Spawn():int Spawn(const char *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* val
17、id, and to populate an Exe_Format data structure describing* how the executable should 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
18、return 0. Otherwise, return an error code.*/int rc;char *exeFileData = 0;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.*/i
19、f(rc = Read_Fully(program, (void*) &exeFileData,&exeFileLength) != 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* execut
20、able file data now.*/Free(exeFileData);exeFileData = 0;/* Start the process! */process = Start_User_Thread(userContext, false);if (process != 0) KASSERT(process-refCount = 2);/* Return Kernel_Thread pointer */*pThread = process; elserc = ENOMEM;return rc;fail:if (exeFileData != 0)Free(exeFileData);i
21、f (userContext != 0)Destroy_User_Context(userContext);return rc;Src/GeekOS/文件中的函数 Switch_To_User_Context ():structuservoid Switch_To_User_Context(struct Kernel_Thread* kthread, Interrupt_State* state)/* Hint: Before executing in user mode, you will need to call* the Set_Kernel_Stack_Pointer() and Sw
22、itch_To_Address_Space()* functions.*/static struct User_Context* s_currentUserContext; /* last 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
23、 mode thread: 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 the
24、re is no* 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/ 文件中的函数 Parse_ELF_Executable ():int Par
25、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* (which needs to be implemented,
26、too)*/if (exeFileLength phnum EXE_MAX_SEGMENTS) if (elfDebug) Print(Too manysegments (%d) in ELFexecutablen, 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-phn
27、um; exeFormat-entryAddr = hdr-entry;phdr = (programHeader *) (exeFileData + hdr-phoff);for (i = 0; i phnum; +i) struct Exe_Segment *segment = &exeFormat-segmentListi;/* Fill in segment offset, length, address* FIXME: should check that segments are valid*/ segment-offsetInFile = phdri.offset; segment
28、-lengthInFile = phdri.fileSize; segment-startAddress = phdri.vaddr; segment-sizeInMemory = phdri.memSize;if (segment-lengthInFile segment-sizeInMemory) if (elfDebug) Print(Segment %d: length in file (%lu) exceeds size in memory (%lu)n,i, segment-lengthInFile, segment-sizeInMemory); return ENOEXEC;/*
29、 Groovy */return 0;src/GeekOS/ 文件中的函数 Destroy_User_Context () void Destroy_User_Context(struct User_Context* userContext) /* Hints:* - you need to free the memory allocated for the user process* - dont forget to free the segment descriptor allocated* for the processs LDT*/*/size = Round_Up_To_Page(m
30、axva) + DEFAULT_USER_STACK_SIZE; argBlockAddr = size;size += argBlockSize;/* Create User_Context */userContext = Create_User_Context(size);if (userContext = 0)return -1;/* Load segment data into memory */for (i = 0; i numSegments; +i) struct Exe_Segment *segment = &exeFormat-segmentListi;memcpy(user
31、Context-memory + segment-startAddress, exeFileData + segment-offsetInFile, segment-lengthInFile);/* Format argument block */Format_Argument_Block(userContext-memory + argBlockAddr, numArgs, argBlockAddr, command);/* Fill in code entry point */ userContext-entryAddr = exeFormat-entryAddr;Fill in addr
32、esses of argument block and stack* (They happen to be the same)*/userContext-argBlockAddr = argBlockAddr; userContext-stackPointerAddr = argBlockAddr;*pUserContext = userContext;return 0;src/GeekOS/ 文件中的函数 Setup_User_Thread()void Setup_User_Thread(struct Kernel_Thread* kthread, struct User_Context*
33、userContext)/* Hints:* - Call Attach_User_Context() to attach the user context* to the Kernel_Thread* - Set up initial thread stack to make it appear that* the thread was interrupted while in user mode* just before the entry point instruction was executed* - The esi register should contain the addre
34、ss of* the argument block*/* Interrupts in user mode MUST be enabled.* All other EFLAGS bits will be clear.*/ulong_t eflags = EFLAGS_IF;unsigned csSelector = userContext-csSelector;unsigned dsSelector = userContext-dsSelector;Attach_User_Context(kthread, userContext);/* Make the threads stack look l
35、ike it was interrupted* while in user mode.*/* Stack segment and stack pointer within user mode. */Push(kthread, dsSelector); /* user ss */Push(kthread, userContext-stackPointerAddr); /* user esp */* eflags, cs, eip */Push(kthread, eflags);Push(kthread, csSelector);Push(kthread, userContext-entryAdd
36、r);Print(Entry addr=%lxn, userContext-entryAddr);/* Push fake error code and interrupt number. */ Push(kthread, 0);Push(kthread, 0);/* Push initial values for general-purpose registers.* The only important register is esi, which we use to* pass the address of the argument block.*/Push(kthread, 0); /
37、* eax */Push(kthread, 0); /* ebx */Push(kthread, 0); /* edx */Push(kthread, 0); /* edx */Push(kthread, userContext-argBlockAddr); /* esi */Push(kthread, 0); /* edi */Push(kthread, 0); /* ebp */* Push initial values for the data segment registers. */Push(kthread, dsSelector); /* ds */Push(kthread, ds
38、Selector); /* es */Push(kthread, dsSelector); /* fs */Push(kthread, dsSelector); /* gs */src/GeekOS/ 文件中的函数 Start_User_Thread() struct Kernel_Thread*Start_User_Thread(struct User_Context* userContext, bool detached) /* Hints:* - Use Create_Thread() to create a new raw thread object* - Call Setup_Use
39、r_Thread() to get the thread ready to* execute in user mode* - Call Make_Runnable_Atomic() to schedule the process* for execution*/struct Kernel_Thread* kthread = Create_Thread(PRIORITY_USER, detached);if (kthread != 0) /* Set up the thread, and put it on the run queue */ Setup_User_Thread(kthread,
40、userContext); Make_Runnable_Atomic(kthread);return kthread;src/GeekOS/ 文件: #include #include #include #include #include #include #include #include #include #include #include #include /* Allocate a buffer for a user string, and* copy it into kernel space.* Interrupts must be disabled.*/static int Cop
41、y_User_String(ulong_t uaddr, ulong_t len, ulong_t maxLen, char *pStr)int rc = 0;char *str;/* Ensure that string isnt too long. */if (len maxLen)return EINVALID;/* Allocate space for the string. */str = (char*) Malloc(len+1);if (str = 0) rc = ENOMEM; goto done;/* Copy data from user space. */if (!Cop
42、y_From_User(str, uaddr, len) rc = EINVALID;Free(str); goto done; strlen = 0;/* Success! */ *pStr = str;done:return rc;/* Null system call.* Does nothing except immediately return control back* to the interrupted user program.* Params:* state - processor registers from user mode* Returns:* always ret
43、urns the value 0 (zero)*/static int Sys_Null(struct Interrupt_State* state) return 0;/* Exit system call.* The interrupted user process is terminated.* Params:* state-ebx - process exit code* Returns:* Never returns to user mode!*/ static int Sys_Exit(struct Interrupt_State* state)Exit(state-ebx);/*
44、 Print a string to the console.* Params:* state-ebx - user pointer of string to be printed* state-ecx - number of characters to print* Returns: 0 if successful, -1 if not*/static int Sys_PrintString(struct Interrupt_State* state)int rc = 0;uint_t length = state-ecx;uchar_t* buf = 0;if (length 0) /*
45、Copy string into kernel. */if (rc = Copy_User_String(state-ebx, length, 1023, (char*) &buf) != 0)goto done;/* Write to console. */Put_Buf(buf, length);done:if (buf != 0)Free(buf);return rc;/* Get a single key press from the console.* Suspends the user process until a key press is available.* Params:
46、* state - processor registers from user mode* Returns: the key code*/ static int Sys_GetKey(struct Interrupt_State* state) return Wait_For_Key();/* Set the current text attributes.* Params:* state-ebx - character attributes to use* Returns: always returns 0*/static int Sys_SetAttr(struct Interrupt_S
47、tate* state)* Params:* state-ebx - pointer to user int where row value should be stored* state-ecx - pointer to user int where column value should be stored* Returns: 0 if successful, -1 otherwise*/static int Sys_GetCursor(struct Interrupt_State* state)int row, col;Get_Cursor(&row, &col);if (!Copy_T
48、o_User(state-ebx, &row, sizeof(int) | !Copy_To_User(state-ecx, &col, sizeof(int) return -1;return 0;/* Set the current cursor position.* Params:* state-ebx - new row value* state-ecx - new column value* Returns: 0 if successful, -1 otherwise*/static int Sys_PutCursor(struct Interrupt_State* state)*
49、Params:* state-ebx - user address of name of executable* state-ecx - length of executable name* state-edx - user address of command string* state-esi - length of command string* Returns: pid of process if successful, error code (ebx, state-ecx, VFS_MAX_PATH_LEN, &program) != 0 |(rc = Copy_User_Strin
50、g(state-edx, state-esi, 1023, &command) != 0)goto done;Enable_Interrupts();/* Now that we have collected the program name and command string* from user space, we can try to actually spawn the process.*/rc = Spawn(program, command, &process);if (rc = 0) KASSERT(process != 0);rc = process-pid;Disable_
51、Interrupts();done:if (program != 0)Free(program);if (command != 0)Free(command);return rc;/* Wait for a process to exit.* Params:* state-ebx - pid of process to wait for* Returns: the exit code of the process,* or error code (ebx);if (kthread = 0)return -12;Enable_Interrupts();exitCode = Join(kthread);Disable_Interrupts();return exitCode;/* Get pid (process id) of current thread.* Params:
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年红外光学测量雷达项目建议书
- 2025年文化内容产品服务项目发展计划
- 中药封包护理的康复效果研究
- 护理急救:原则与流程
- 运动平板试验护理要点总结
- 管道护理PDCA循环详解
- 危重症监护核心护理技术梳理
- 护理入门课程课件
- 告别任性课件
- 护理常规康复护理
- 物流运输服务方案投标文件(技术方案)
- 南阳市劳务合同范本
- 产业园招商培训
- 2026年齐齐哈尔高等师范专科学校单招综合素质考试题库必考题
- 2018版公路工程质量检验评定标准分项工程质量检验评定表路基土石方工程
- 导尿管相关尿路感染(CAUTI)防控最佳护理实践专家共识解读
- 2025年广东深圳高中中考自主招生数学试卷试题(含答案详解)
- SMETA员工公平职业发展管理程序-SEDEX验厂专用文件(可编辑)
- 2024年湖南高速铁路职业技术学院公开招聘辅导员笔试题含答案
- 水泵购买合同(标准版)
- ICU获得性衰弱课件
评论
0/150
提交评论