
计算机操作系统实验-运行用户态程序.doc
13页西北工业大学 操作系统实验 实验报告一、实验目的掌握在GeekOS系统用户态模式下加载并运行可执行程序的方法二、实验要求1. 按照实验讲义P127页中的设计要求,实现在用户态模式下加载并运行可执行程序的代码,给出关键函数的代码以及实验结果三、实验过程及结果答:核心函数代码如下:================== user.c ===============//产生一个进程(用户态)int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread){ //TODO("Spawn a process by reading an executable from a filesystem"); int rc; char *exeFileData = 0; ulong_t exeFileLength; struct User_Context *userContext = 0; struct Kernel_Thread *process = 0; struct Exe_Format exeFormat; if ((rc = Read_Fully(program, (void**) &exeFileData, &exeFileLength)) != 0 ) { Print("Failed to Read File %s!\n", program); goto fail; } if((rc = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat)) != 0 ) { Print("Failed to Parse ELF File!\n"); goto fail; } if((rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext)) != 0) { Print("Failed to Load User Program!\n"); goto fail; } //在堆分配方式下释放内存并再次初始化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 rc = ENOMEM; return rc; fail: //如果新进程创建失败则注销User_Context对象 if (exeFileData != 0) Free(exeFileData);//释放内存 if (userContext != 0) Destroy_User_Context(userContext);//销毁进程对象 return rc;}-------------------------------------//切换至用户上下文void Switch_To_User_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state){ static struct User_Context* s_currentUserContext; /* last user context used */ //extern int userDebug; struct User_Context* userContext = kthread->userContext; KASSERT(!Interrupts_Enabled()); if (userContext == 0) { //userContext为0表示此进程为核心态进程就不用切换地址空间 return; } if (userContext != s_currentUserContext) { ulong_t esp0; //if (userDebug) Print("A[%p]\n", kthread); Switch_To_Address_Space(userContext);//为用户态进程时则切换地址空间 esp0 = ((ulong_t) kthread->stackPage) + PAGE_SIZE; //if (userDebug) // Print("S[%lx]\n", esp0); /* 新进程的核心栈. */ Set_Kernel_Stack_Pointer(esp0);//设置内核堆栈指针 /* New user context is active */ s_currentUserContext = userContext; }} ================== elf.c ====================int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat){ int i; elfHeader *head=(elfHeader*)exeFileData; programHeader *proHeader=(programHeader *)(exeFileData+head->phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLength>head->ehsize+head->phentsize*head->phnum); KASSERT(head->entry%4==0); exeFormat->numSegments=head->phnum; exeFormat->entryAddr=head->entry; for(i=0;i
