ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:134.54KB ,
资源ID:6136191      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/6136191.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(计算机操作系统实验运行用户态程序.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

计算机操作系统实验运行用户态程序.docx

1、计算机操作系统实验运行用户态程序西北工业大学 操作系统实验 实验报告一、实验目的掌握在GeekOS系统用户态模式下加载并运行可执行程序的方法。二、实验要求1. 按照实验讲义P127页中的设计要求,实现在用户态模式下加载并运行可执行程序的代码,给出关键函数的代码以及实验结果。三、实验过程及结果答:核心函数代码如下:= user.c =/产生一个进程(用户态)int Spawn(const char *program, const char *command, struct Kernel_Thread *pThread) /TODO(Spawn a process by reading an ex

2、ecutable 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);

3、 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; /在堆分配方式下释放内存并再次初始化exeF

4、ileData 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: /如果新进程创建

5、失败则注销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 us

6、er 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%pn, kthread); Switch_To_Addr

7、ess_Space(userContext);/为用户态进程时则切换地址空间 esp0 = (ulong_t) kthread-stackPage) + PAGE_SIZE; /if (userDebug) / Print(S%lxn, esp0); /* 新进程的核心栈. */ Set_Kernel_Stack_Pointer(esp0);/设置内核堆栈指针 /* New user context is active */ s_currentUserContext = userContext; = elf.c =int Parse_ELF_Executable(char *exeFileDa

8、ta, ulong_t exeFileLength, struct Exe_Format *exeFormat) int i; elfHeader *head=(elfHeader*)exeFileData; programHeader *proHeader=(programHeader *)(exeFileData+head-phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLengthhead-ehsize+head-phentsize*head-phnum); KASSERT(head-entry%4=0); exeFormat-num

9、Segments=head-phnum; exeFormat-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-

10、segmentListi.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 Us

11、er_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 = A

12、llocate_Segment_Descriptor(); if (0 = UserContext-ldtDescriptor) goto fail; /初始化段描述符 Init_LDT_Descriptor(UserContext-ldtDescriptor, UserContext-ldt, NUM_USER_LDT_ENTRIES); /新建一个LDT选择子 UserContext-ldtSelector = Selector(KERNEL_PRIVILEGE, true, Get_Descriptor_Index(UserContext-ldtDescriptor); /新建一个文本段

13、描述符 Init_Code_Segment_Descriptor( &UserContext-ldt0, (ulong_t) UserContext-memory, size / PAGE_SIZE, USER_PRIVILEGE ); /新建一个数据段 Init_Data_Segment_Descriptor( &UserContext-ldt1, (ulong_t) UserContext-memory, size / PAGE_SIZE, USER_PRIVILEGE ); /新建数据段和文本段选择子 UserContext-csSelector = Selector(USER_PRIV

14、ILEGE, false, 0); UserContext-dsSelector = Selector(USER_PRIVILEGE, false, 1); /将引用数清0 UserContext-refCount = 0; return UserContext;fail: if (UserContext != 0) if (UserContext-memory != 0) Free(UserContext-memory); Free(UserContext); return 0;-/摧毁用户上下文void Destroy_User_Context(struct User_Context* u

15、serContext) /TODO(Destroy a User_Context); /释放占用的LDT Free_Segment_Descriptor(userContext-ldtDescriptor); userContext-ldtDescriptor=0; /释放内存空间 Free(userContext-memory); userContext-memory=0; /释放userContext本身占用的内存 Free(userContext); userContext=0;-int Load_User_Program(char *exeFileData,ulong_t exeFil

16、eLength,struct Exe_Format *exeFormat,const char *command,struct User_Context *pUserContext) /TODO(Load a user executable into a user memory space using segmentation); int i; ulong_t maxva = 0;/要分配的最大内存空间 unsigned numArgs;/进程数目 ulong_t argBlockSize;/参数块的大小 ulong_t size, argBlockAddr;/参数块地址 struct Use

17、r_Context *userContext = 0; /计算用户态进程所需的最大内存空间 for (i = 0; i numSegments; +i) /elf.h struct Exe_Segment *segment = &exeFormat-segmentListi; ulong_t topva = segment-startAddress + segment-sizeInMemory; /* FIXME: range check */ if (topva maxva) maxva = topva; Get_Argument_Block_Size(command, &numArgs,

18、&argBlockSize);/获取参数块信息 size = Round_Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE; argBlockAddr = size; size += argBlockSize; userContext = Create_User_Context(size);/按相应大小创建一个进程 if (userContext = 0)/如果为核心态进程 return -1; for (i = 0; i numSegments; +i) struct Exe_Segment *segment = &exeFormat-segmentLi

19、sti; /根据段信息将用户程序中的各段内容复制到分配的用户内存空间 memcpy(userContext-memory + segment-startAddress, exeFileData + segment-offsetInFile,segment-lengthInFile); /格式化参数块 Format_Argument_Block(userContext-memory + argBlockAddr, numArgs, argBlockAddr, command); /初始化数据段,堆栈段及代码段信息 userContext-entryAddr = exeFormat-entryAd

20、dr; userContext-argBlockAddr = argBlockAddr; userContext-stackPointerAddr = argBlockAddr; /将初始化完毕的User_Context赋给*pUserContext *pUserContext = userContext; return 0;/成功-/将用户态的进程复制到内核缓冲区bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t bufSize) struct User_Context * UserContext = g_cu

21、rrentThread-userContext; /-: check if memory if validated if (!Validate_User_Memory(UserContext,srcInUser, bufSize) return false; memcpy(destInKernel, UserContext-memory + srcInUser, bufSize); return true;-/将内核态的进程复制到用户态bool Copy_To_User(ulong_t destInUser, void* srcInKernel, ulong_t bufSize) struct

22、 User_Context * UserContext = g_currentThread-userContext; if (!Validate_User_Memory(UserContext, destInUser, bufSize) return false; memcpy(UserContext-memory + destInUser, srcInKernel, bufSize); return true;-/切换到用户地址空间void Switch_To_Address_Space(struct User_Context *userContext) ushort_t ldtSelect

23、or= userContext-ldtSelector;/* Switch to the LDT of the new user context */ _asm_ _volatile_ (lldt %0:a(ldtSelector);= kthread.c =添加头文件 #include -/创建一个用户进程/*static*/ void Setup_User_Thread(struct Kernel_Thread* kthread, struct User_Context* userContext) ulong_t eflags = EFLAGS_IF; unsigned csSelecto

24、r=userContext-csSelector;/CS选择子 unsigned dsSelector=userContext-dsSelector;/DS选择子 Attach_User_Context(kthread, userContext); /初始化用户态进程堆栈,使之看上去像刚被中断运行一样 /分别调用Push函数将以下数据压入堆栈 Push(kthread, dsSelector); /数据选择子 Push(kthread, userContext-stackPointerAddr); /堆栈指针 Push(kthread, eflags); /Eflags Push(kthrea

25、d, csSelector); /文本选择子 Push(kthread, userContext-entryAddr); /程序计数器 Push(kthread, 0); /错误代码(0) Push(kthread, 0); /中断号(0) /初始化通用寄存单元,将ESI用户传递参数块地址 Push(kthread, 0); /* eax */ Push(kthread, 0); /* ebx */ Push(kthread, 0); /* edx */ Push(kthread, 0); /* edx */ Push(kthread, userContext-argBlockAddr); /

26、* esi */ Push(kthread, 0); /* edi */ Push(kthread, 0); /* ebp */ /初始化数据段寄存单元 Push(kthread, dsSelector); /* ds */ Push(kthread, dsSelector); /* es */ Push(kthread, dsSelector); /* fs */ Push(kthread, dsSelector); /* gs */ /开始用户进程struct Kernel_Thread* Start_User_Thread(struct User_Context* userContext

27、, bool detached) struct Kernel_Thread* kthread = Create_Thread(PRIORITY_USER, detached); if (kthread != 0) Setup_User_Thread(kthread, userContext); Make_Runnable_Atomic(kthread); return kthread; = syscall.c =/需在此文件别的函数前增加一个函数,函数名为Copy_User_String,它被函数Sys_PrintString调用,具体实现如下:static int Copy_User_Str

28、ing(ulong_t uaddr, ulong_t len, ulong_t maxLen, char *pStr) int rc = 0; char *str; if (len maxLen) /超过最大长度 return EINVALID; str = (char*) Malloc(len+1); /为字符串分配空间 if (0 = str) rc = ENOMEM; goto fail; if (!Copy_From_User(str, uaddr, len) /从用户空间中复制数据 rc = EINVALID; Free(str); goto fail; strlen = 0; /成功 *pStr = str;fail: return rc;-static int Sys_Exit(struct Interrupt_State* st

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1