计算机操作系统实验_运行用户态程序 下载本文

内容发布更新时间 : 2024/5/16 3:59:03星期一 下面是文章的全部内容请认真阅读。

实用标准文案

西北工业大学 操作系统实验 实验报告

一、实验目的

掌握在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;iphnum;i++) { exeFormat->segmentList[i].offsetInFile=proHeader->offset; exeFormat->segmentList[i].lengthInFile=proHeader->fileSize; exeFormat->segmentList[i].startAddress=proHeader->vaddr; exeFormat->segmentList[i].sizeInMemory=proHeader->memSize; exeFormat->segmentList[i].protFlags=proHeader->flags; proHeader++; } return 0; }

=================== 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();

精彩文档