


下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、课程设计说明书学 院:计算机科学与工程学院专 业:计算机科学与技术姓名: 天驹学号:0900310327指导教师:黄廷辉2012年3 月 5 日操作系统课程设计报告GeekOS操作系统的研究与实现(项目0项目2)一、实验目的:熟悉GeekOS项目编译运行环境、核态进程的实现、用户态进程的实现、 进程调度策略和算法实现、分页存储管理的实现和文件系统的实现等。二、项目设计要求:GeekOSg计项目0:1. 搭建GeekOS勺编译和调试平台,掌握 GeekOS勺核进程工作原理。2. 熟悉键盘操作函数,编程实现一个核进程。该进程的功能是:接受键盘输 入的字符并显示到屏幕上,当输入 Ctrl+D时,结束
2、进程的运行。GeekOSg计项目1:1. 修改/geekos/elf.c文件:在函数Parse_ELF_Executable()中添加代码,分 析ELF格式的可执行文件(包括分析得出ELF文件头、程序头,获取可执行 文件长度、代码段、数据段等信息),并填充Exe_Format数据结构中的域值。2. 掌握GeekOS在核心态运行用户程序的原理,为项目2的实现做准备。GeekOSS计项目2:本项目要求用户对以下几个文件进行修改:1. src/GeekOS/user.c文件中的函数Spawn(),其功能是生成一个新的用户 级进程。2. src/GeekOS/usre.c 文件中的函数 Switch_
3、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结构。(3) Copy_F
4、rom_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、件中改写生成第一个用户态进程的函数调用:Spawnnit_Process(void)。需要注意的是:作为与用户沟通的界面,GeekOS 提供了一个简单的Shell,保存在PFAT文件系统,所以GeekOS系统启动后, 应启动shell程序/c/shell.exe运行,所以需要将/c/shell.exe作为可执行文件传递给Spawn函数的program参数,创建第一个用户态进程,然后由 它来创建其他进程。添加代码运行成功后,GeekOS就可以挂载shell,并能运行测试文件c.exe和 b.exe。三、如何建立开发环境:(一) 利用linux安装盘安装了 ubuntu1O.1O版本的linux操
7、作系统环境;(二) 联网后通过系统里的更新管理器更新了系统,并安装了语言包和必要的 驱动。(三) 在ubuntu软件中心下载安装了 NASM汇编器、Bochs PC模拟器以及 bochs-x插件(保证ubuntu10.10环境下的bochs正常运行)。四、项目设计原理:Make工作原理:在默认的方式下,只要输入 make命令就可以工作。具体的处理过程如下:(1)make会在当前目录下找文件名为“ Makefile ”或“ makefile ”的文件。 如果找到,它会找文件中的第一个目标文件(target ),在上面的例子中, 它会找到“ edit ”这个文件,并把这个文件作为最终的目标文件。(
8、3) 如果edit文件不存在,或是edit所依赖的后面的.o文件的修改时间要比edit这个文件新,那么,就会执行后面所定义的命令来生成edit这个文件。(4) 如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标 为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件(这有点 像一个堆栈的过程)。(5) 如果指定的C文件和H文件是存在的,make会生成.o文件,然后再用.o 文件生成make的最终任务,也就是生成执行文件 edit。GeekOS的 makefile 文件功能:(1) 指定GeekOS如何被编译,哪些源文件被编译,哪些用户程序被编译 等等。通常不同项目的编译
9、仅仅需要修改这一部分。(2) 定义了编译GeekOS要用到的工具程序。(4)指定系统编译生成的指定文件。GeekOS项目的开发流程:1. 开始一个GeekOS项目,第一步是添加相应的代码。2. 在Linux下利用make命令编译系统,生成系统镜像文件。 $ cd /projectO/build $ make depend $ make3. 编写每个项目相应的Bochs的配置文件。4. 运行Bochs模拟器,执行GeekOS核。 $ cd /bochs $ bochs 运行后,屏幕上会有一些提示。运行GeekOS选择Beginsimulation ,如果GeekOS编译成功,并且bochs的配置
10、也 没问题,将会看到一个模拟 VGA的文本窗口,Geekos就能 运行程序输出相应信息(每个环境具体运行的命令格式会有一些不同)核线程的建立流程:Spawn («ReadFuliyOParsed LF_ExcutabSe()!LLcad_User_Pr ogram ()5卜-Start User Thread ()tSetup User Thread ()Attach_User.Context ()用户态进程创建流程五、项目设计的具体实现(程序代码):GeekOSg计项目0:Main.c 文件:#in clude vgeekos/booti nfo.h> #include &l
11、t;geekos/string.h> #i nclude <geekos/scree n.h> #i nclude <geekos/mem.h>#i nclude vgeekos/crc32.h>#in elude <geekos/tss.h>#in elude <geekos/i nt.h>#i nclude <geekos/kthread.h>#include <geekos/trap.h>#i nclude <geekos/timer.h>#i nclude <geekos/keyboa
12、rd.h>/* Kernel C code entry point.* Initializes kernel subsystems, mounts filesystems,* and spaw ns init process.*/void Mai n( struct Boot_I nfo* boot Info) _In it_BSS();Ini t_Scree n();In it_Mem(bootI nfo);In it_CRC32();In it_TSS();lnit_ln terrupts();In it_Scheduler();In it_Traps();In it_Timer()
13、;In it_Keyboard();Set_Curre nt_Attr(ATTRIB(BLACK, GREEN|BRIGHT); Prin t("Welcome to GeekOS!n");Set_Curre nt_Attr(ATTRIB(BLACK, GRAY);void EchoCo un t()Keycode keycode;int count;coun t=0;while (1)if ( Read_Key( & keycode ) _if(keycode & 0x4000) = 0x4000)if(Wait_For_Key() & 0x00f
14、f) = 'd')/Pri nt("%c",Wait_For_Key();Set_Curre nt_Attr(ATTRIB(BLACK, RED);Print("Ctrl+dIs Entered! Program Ended!");Exit(1);elseif ( !(keycode & KEY_SPECIAL_FLAG&&!(keycode &KEY_RELEASE_FLAG)keycode &= Oxff;coun t=co un t+1;Set_Current_Attr(ATTRIB(BLAC
15、K, CYAN); Print( "%c", (keycode = 'r') ? 'n' : keycode );if(keycode='r')coun t=co un t-1;Set_Curre nt_Attr(ATTRIB(AMBER, BLUE);Prin t("The counnts is %d ",co un t);Prin t("n");coun t=0;struct Kern el_Thread *kerThd;kerThd = Start_Kernel_Thread(&a
16、mp;EchoCou nt, 0 , PRIORITY_NORMAL, false);/* Now this thread is done. */Exit(O);GeekOS设计项目1:Elf.c文件: #i nclude <geekos/err no .h> #in clude <geekos/kassert.h> #i nclude <geekos/ktypes.h>#i nclude vgeekos/scree n.h> /* for debug Prin t() stateme nts */#in clude <geekos/pfat.h
17、>#i nclude <geekos/malloc.h>#include <geekos/string.h>#include <geekos/elf.h>/* From the data of an ELF executable, determ ine how its segme nts* n eed to be loaded into memory.* param exeFileData buffer containing the executable file* param exeFileLength length of the executabl
18、e file in bytes* param exeFormat structure describ ing the executable's segme nts* and entry address; to be filled in* retur n 0 if successful, < 0 on error*/int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLe ngth, struct Exe_Format *exeFormat) _/* TODO("Parse an ELF executabl
19、e image");*/int i;elfHeader *head=(elfHeader*)exeFileData;programHeader*proHeader=(programHeader*)(exeFileData+head->phoff);KASSERT(exeFileData!=NULL);KASSERT(exeFileLe ngth>head->ehsize+head->phe ntsize*head->ph nu m); KASSERT(head->e ntry%4=0);exeFormat- >nu mSegme nts=he
20、ad->ph num;exeFormat->e ntryAddr=head->e ntry;for(i=0;i<head->ph nu m;i+)exeFormat->segme ntListi.offset InF ile=proHeader->offset;exeFormat->segme ntListi .len gthI nF ile=proHeader->fileSize;exeFormat->segme ntListi.startAddress=proHeader->vaddr;exeFormat->segme
21、 ntListi.size In Memory=proHeader->memSize;exeFormat->segme ntLtFlags=proHeader->flags;proHeader+;return 0;GeekOS设计项目2:Src/GeekOS/user.c 文件中的函数 Spawn():int Spawn(const char *program, const char *command, struct Kernel_Thread*pThread)/* Hi nts:* - Call Read_Fully() to load the en tir
22、e executable into a memory buffer* - Call Parse_ELF_Executable() to verify that the executable is* valid, and to populate an Exe_Format data structure describ ing* how the executable should be loaded* - Call Load_User_Program() to create a User_C on text with the loaded* program* - Call Start_User_T
23、hread() with the new User_Co ntext* 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;ulong_t exeFileLe ngth;struct User_C on text *userC on text = 0;struct Kern el_Thread *process = 0;struct Exe_Format exe
24、Format;/* Load the executable file data, parse ELF headers,* and load code and data segme nts into user memory.*/if(rc = Read_Fully(program, (void*) &exeFileData,& exeFileLe ngth) != 0 |(rc= Parse_ELF_Executable(exeFileData,exeFileLe ngth,& exeFormat) != 0 |(rc = Load_User_Program(exeFil
25、eData, exeFileLe ngth, &exeFormat, comma nd, &userC on text) != 0)goto fail;/* User program has bee n loaded, so we can free the* executable file data now.*/Free(exeFileData);exeFileData = 0;/* Start the process! */process = Start_User_Thread(userC on text, false); if (process != 0) KASSERT(
26、process->refCou nt = 2);/* Retur n Kern el_Thread poin ter */*pThread = process; elserc = ENOMEM;return rc;fail:if (exeFileData != 0)Free(exeFileData);if (userCo ntext != 0)Destroy_User_C on text(userC on text);return rc;structuserSrc/GeekOS/user.c 文件中的函数 Switch_To_User_C on text (): voidSwitch_T
27、o_User_C on text(structKern el_Thread*kthread,In terrupt_State* state) _/* Hint: Before executi ng in user mode, you will n eed to call* the Set_Kernel_Stack_Poi nter() and Switch_To_Address_Space()* functions.*/static structUser_C on text* s_curre ntUserC on text;/* lastcon text used */struct User_
28、C on text* userC on text = kthread->userC on text;/* FIXME: could avoid resetting ss0/esp0 if not returning* to user space.*/KASSERT(!I nterrupts_E nabled();if (userC on text = 0) /* Kernel mode thread: no n eed to switch address space. */ return;/* Switch only if the user con text is in deed dif
29、fere nt */if (userC on text != s_curre ntUserC on text) ulong_t esp0;/* Switch to address space of user con text */ Switch_To_Address_Space(userC on text);/* By definition, when returning to user mode there is no* con text remai ning on the kernel stack.*/esp0 = (ulo ng_t) kthread->stackPage) + P
30、AGE_SIZE;/* Change to the kernel stack of the new process. */ Set_Kernel_Stack_Poi nter(espO);/* New user con text is active */ s_curre ntUserC on text = userC on text; _src/GeekOS/elf.c 文件中的函数 Parse_ELF_Executable ():int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLe ngth, struct Exe_For
31、mat *exeFormat) _elfHeader *hdr;programHeader *phdr;int i;hdr = (elfHeader *) exeFileData;/* FIXME: when checking offsets, we really ought to be* check ing overflow cases. Need to use fun cti ons from* ran ge.h (which n eeds to be impleme nted, too)*/if (exeFileLe ngth < sizeof(elfHeader) | strnc
32、mp(exeFileData, "x7F""ELF", 4) != 0) if (elfDebug) Print("Not an ELF executablen"); return ENOEXEC;if (hdr->ph num > EXE_MAX_SEGMENTS) if (elfDebug) Prin t("Too man ysegme nts (%d) in ELFexecutablen", hdr->ph nu m);return ENOEXEC;if(exeFileLe ngth<
33、 hdr->phoff +(hdr->ph num*sizeof(programHeader) if (elfDebug) Prin t("Not eno ugh room for program header n"); return ENOEXEC;exeFormat- >nu mSegme nts = hdr->ph num;exeFormat->e ntryAddr = hdr->e ntry;phdr = (programHeader *) (exeFileData + hdr->phoff);for (i = 0; i &
34、lt; hdr->ph num; +i) struct Exe_Segme nt *segme nt = &exeFormat->segme ntListi;/* Fill in segme nt offset, le ngth, address* FIXME: should check that segme nts are valid*/segme nt->offset InF ile = phdri.offset;segme nt->le ngthl nF ile = phdri.fileSize;segme nt->startAddress = ph
35、dri.vaddr; segme nt->size In Memory = phdri.memSize;if (segme nt->le ngthl nF ile > segme nt->sizel nM emory) if(elfDebug) Print("Segment %d: length in file (%lu) exceedssize in memory (%lu)n",i, segment->lengthlnFile, segment->sizelnMemory); return ENOEXEC;/* Groovy */re
36、turn 0; src/GeekOS/userseg.c 文件中的函数 Destroy_User_Context () void Destroy_User_C on text(struct User_C on text* userC on text) 一/* Hi nts:* - you n eed to free the memory allocated for the user process* - don't forget to free the segme nt descriptor allocated* for the process's LDT*/ TODO(&qu
37、ot;Destroy a User_Co ntext");/* Free the con text's LDT descriptor */Free_Segme nt_Descriptor(userC on text->ldtDescriptor); userC on text->ldtDescriptor=0;/* Free the con text's memory */Free(userC on text->memory);userC on text->memory=0;Free(userC on text);userC on text=0
38、; src/GeekOS/userseg.c 文件中的函数 Load_User_Program() int Load_User_Program(char *exeFileData, ulong_t exeFileLe ngth, struct Exe_Format *exeFormat, const char *comma nd, struct User_C on text *pUserC on text) _/* Hi nts:* - Determine where in memoryeach executable segment will be placed* - Determine si
39、ze of argument block and where it memory it will* be placed* - Copy each executable segme nt into memory* - Format argume nt block in memory* - In the created User_C on text object, set code entry point* address, argument block address, and initial kernel stack poi nter* address*/int i;ulong_t maxva
40、 = 0;un sig ned nu mArgs;ulong_t argBlockSize;ulong_t size, argBlockAddr;struct User_C on text *userC on text = 0;/* Find maximum virtual address */for (i = 0; i < exeFormat- >nu mSegme nts; +i) struct Exe_Segme nt *segme nt = &exeFormat->segme ntListi; ulong_t topva = segme nt->star
41、tAddress + segme nt->sizel nM emory;/* FIXME: range check */if (topva > maxva)maxva = topva;/* Determi ne size required for argume nt block */Get_Argume nt_Block_Size(comma nd, &nu mArgs, & argBlockSize);/* Now we can determ ine the size of the memory block n eeded* to run the process.
42、*/size = Roun d_Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE; argBlockAddr = size;size += argBlockSize;/* Create User_C on text */userC on text = Create_User_C on text(size);if (userC on text = 0)return -1;/* Load segme nt data into memory */for (i = 0; i < exeFormat- >nu mSegme nts; +i) struct
43、 Exe_Segme nt *segme nt = &exeFormat->segme ntListi;memcpy(userC on text->memory + segme nt->startAddress, exeFileData + segme nt->offsetl nF ile, segme nt->le ngthl nFile);/* Format argume nt block */Format_Argume nt_Block(userC on text->memory+ argBlockAddr, nu mArgs,argBlock
44、Addr, comma nd);/* Fill in code entry point */userC on text->e ntryAddr = exeFormat->e ntryAddr;/* Fill in addresses of argume nt block and stack* (They happe n to be the same)*/userCo ntext->argBlockAddr = argBlockAddr;userCo ntext->stackPoi nterAddr = argBlockAddr;*pUserC on text = use
45、rC on text;return 0;src/GeekOS/kthread.c 文件中的函数 Setup_User_Thread() void Setup_User_Thread(struct Kern el_Thread* kthread, struct User_C on text* userC on text) 一 一/* Hi nts:* - Call Attach_User_C on text() to attach the user con text* to the Kern el_Thread* - Set up initial thread stack to make it
46、appear that* the thread was in terrupted while in user mode* just before the entry point in structi on was executed* - The esi register should contain the address of* the argume nt block*/* In terrupts in user mode MUST be en abled.* All other EFLAGS bits will be clear.*/ulo ng_t eflags = EFLAGS_IF;
47、un sig ned csSelector = userC on text->csSelector;un sig ned dsSelector = userC on text->dsSelector;Attach_User_C on text(kthread, userC on text);/* Make the thread's stack look like it was in terrupted* while in user mode.*/* Stack segme nt and stack poin ter with in user mode. */Push(kth
48、read, dsSelector); /* user ss */Push(kthread, userC on text->stackPoi nterAddr); /* user esp */* eflags, cs, eip */Push(kthread, eflags);Push(kthread, csSelector);Push(kthread, userC on text->e ntryAddr);Print("Entry addr=%lxn", userContext->entryAddr);/* Push fake error code and
49、interrupt number. */Push(kthread, 0);Push(kthread, 0);/* Push in itial values for gen eral-purpose registers.* The on ly importa nt register is esi, which we use to* pass the address of the argume nt block.*/Push(kthread, 0); /* eax */Push(kthread, 0); /* ebx */Push(kthread, 0); /* edx */Push(kthrea
50、d, 0); /* edx */Push(kthread, userCo ntext->argBlockAddr); /* esi */Push(kthread, 0); /* edi */Push(kthread, 0); /* ebp */* Push in itial values for the data segme nt registers. */Push(kthread, dsSelector); /* ds */Push(kthread, dsSelector); /* es */Push(kthread, dsSelector); /* fs */Push(kthread
51、, dsSelector); /* gs */src/GeekOS/kthread.c 文件中的函数 Start_User_Thread()struct Kern el_Thread*Start_User_Thread(struct User_C on text* userC on text, bool detached) 一/* Hi nts:* - Use Create_Thread() to create a new "raw" thread object* - Call Setup_User_Thread() to get the thread ready to*
52、execute in user mode* - Call Make_R unn able_Atomic() to schedule the process* for executi on*/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, userC on text); Make_Ru nn able_Atom
53、ic(kthread); 一 一return kthread;src/GeekOS/Syscall.c 文件:#i nclude <geekos/syscall.h>#i nclude <geekos/err no .h>#i nclude <geekos/kthread.h>#in clude <geekos/i nt.h>#include <geekos/elf.h>#i nclude <geekos/malloc.h>#i nclude <geekos/scree n.h>#i nclude <ge
54、ekos/keyboard.h>#include <geekos/string.h>#in clude <geekos/user.h>#i nclude <geekos/timer.h>#i nclude <geekos/vfs.h>/* Allocate a buffer for a user stri ng, and* copy it into kernel space.* In terrupts must be disabled.*/maxLe n,static int Copy_User_String(ulong_tuaddr, u
55、long_t len, ulong_tchar *pStr)int rc = 0;char *str;/* En sure that stri ng isn't too long. */if (le n > maxLe n)return EINVALID;/* Allocate space for the string. */ str = (char*) Malloc(le n+1);if (str = 0) rc = ENOMEM;goto done;/* Copy data from user space. */if (!Copy_From_User(str, uaddr,
56、le n) rc = EINVALID;Free(str);goto done;strle n = '0'/* Success! */*pStr = str;done:return rc;/* Null system call.* Does no thi ng except immediately retur n con trol back* to the in terrupted user program.* Params:* state - processor registers from user mode* Returns:* always returns the va
57、lue 0 (zero)*/static int Sys_Null(struct In terrupt_State* state) 一 一return 0;/* Exit system call.* The in terrupted user process is term in ated.* Params:* state->ebx - process exit code* Returns:* Never retur ns to user mode!*/static int Sys_Exit(struct Interrupt_State* state)Exit(state->ebx);/* Print a stri ng to the con sole.* Params:* state->ebx - user poin ter of stri ng to be prin ted* state->ecx - nu mber of characters to print* Retur ns: 0 if successful, -1 if not*/static int Sys_Pri ntStri ng(struct In terrupt_State* state) 一 一int rc = 0;ui nt_t len
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 引导幼儿园小班的团队协作与竞争意识计划
- 备考育婴师考试的策略试题及答案
- 2024年育婴师备考策略试题及答案
- 全媒体运营师行业发展试题及答案
- 2025执业兽医复习要点总结试题及答案
- 2024年图形界面设计试题及答案
- 黑龙江省佳木斯市汤原县高级中学2024-2025学年高三下期中考试(历史试题文)试题含解析
- 黑龙江省哈六中2025年全国新高三下学期开学大联考试题数学试题含解析
- 黑龙江省哈尔滨旭东中学2024-2025学年初三下学期化学试题统练(七)(期中模拟)含解析
- 黑龙江省牡丹江市绥芬河市2024-2025学年五下数学期末复习检测模拟试题含答案
- 基坑工程土方开挖支护与降水监理实施细则
- 数字信号处理(课件)
- 沉淀理论课件
- 最新高三主题班会:行百里者半九十课件
- 土方回填施工记录表
- 体育调查问卷
- 公司样品标识卡
- 英语人教新起点(一起)四年级下册-Unit 3 Lesson 2 Travel plans教学设计
- SONYα300α350使用手册
- 海外专家部分项目简介
- 医疗美容主诊医师备案服务指南
评论
0/150
提交评论