实用标准文案
西北工业大学 操作系统实验 实验报告
一、实验目的
掌握在GeekOS系统用户态模式下加载并运行可执行程序的方法。
二、实验要求
1. 按照实验讲义P127页中的设计要求,实现在用户态模式下加载并运行可执行程序的代码,给出关键函数的代码以及实验结果。
三、实验过程及结果
答:核心函数代码如下:
================== user.c =============== //产生一个进程(用户态)
int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread) { //TODO(\ 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(\ goto fail; } if((rc = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat)) != 0 ) { Print(\ goto fail; } if((rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext)) != 0) { Print(\ 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(\ Switch_To_Address_Space(userContext);//为用户态进程时则切换地址空间 esp0 = ((ulong_t) kthread->stackPage) + PAGE_SIZE; //if (userDebug) // Print(\ /* 新进程的核心栈. */ 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
=================== userseg.c ===================
//需在此文件各函数前增加一个函数,此函数的功能是按给定的大小创建一个用户级进程上下文,具体实现如下:
//函数功能:按给定的大小创建一个用户级进程上下文
static struct User_Context* Create_User_Context(ulong_t size) { struct User_Context * UserContext; size = Round_Up_To_Page(size);
UserContext = (struct User_Context *)Malloc(sizeof(struct User_Context)); if (UserContext != 0)
UserContext->memory = Malloc(size); //为核心态进程 else
goto fail; //内存为空
if (0 == UserContext->memory) goto fail;
memset(UserContext->memory, '\\0', size); UserContext->size = size;
//以下为用户态进程创建LDT(段描述符表) //新建一个LDT描述符
UserContext->ldtDescriptor = Allocate_Segment_Descriptor();
精彩文档