1、Failed to Parse ELF File! if(rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext) != 0)Failed to Load User Program! /在堆分配方式下释放内存并再次初始化exeFileData Free(exeFileData); exeFileData = 0; /* 开始用户进程,调用Start_User_Thread函数创建一个进程并使其进入准备运行队列*/ process = Start_User_Thread(userCo
2、ntext, false); if (process != 0) KASSERT(process-refCount = 2); /* 返回核心进程的指针 */ *pThread = process; rc = process-pid;/记录当前进程的ID else rc = ENOMEM; return rc; fail: /如果新进程创建失败则注销User_Context对象 if (exeFileData ! Free(exeFileData);/释放内存 if (userContext ! Destroy_User_Context(userContext);/销毁进程对象 return
3、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 (user
4、Context = 0) /userContext为0表示此进程为核心态进程就不用切换地址空间 return; if (userContext != s_currentUserContext) ulong_t esp0; /if (userDebug) Print(A%pn, kthread); Switch_To_Address_Space(userContext);/为用户态进程时则切换地址空间 esp0 = (ulong_t) kthread-stackPage) + PAGE_SIZE; /if (userDebug) / Print(S%lxn, esp0); /* 新进程的核心栈.
5、 */ 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=(progra
6、mHeader *)(exeFileData+head-phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLengthhead-ehsize+head-phentsize*head-phnum); KASSERT(head-entry%4=0); exeFormat-numSegments=head-phnum;entryAddr=head-entry; for(i=0;isegmentListi.offsetInFile=proHeader-offset;segmentListi.lengthInFile=proHeader-fileSiz
7、e;segmentListi.startAddress=proHeader-vaddr;segmentListi.sizeInMemory=proHeader-memSize;segmentListi.protFlags=proHeader-flags; proHeader+; return 0;= userseg.c =/需在此文件各函数前增加一个函数,此函数的功能是按给定的大小创建一个用户级进程上下文,具体实现如下:/函数功能:按给定的大小创建一个用户级进程上下文static struct User_Context* Create_User_Context(ulong_t size) st
8、ruct User_Context * UserContext; size = Round_Up_To_Page(size); UserContext = (struct User_Context *)Malloc(sizeof(struct User_Context); if (UserContext ! UserContext-memory = Malloc(size); /为核心态进程 goto fail; /内存为空 if (0 = UserContext-memory) memset(UserContext-memory, 0, size);size = size; /以下为用户态进
9、程创建LDT(段描述符表) /新建一个LDT描述符ldtDescriptor = Allocate_Segment_Descriptor();ldtDescriptor) /初始化段描述符 Init_LDT_Descriptor(UserContext-ldtDescriptor, UserContext-ldt, NUM_USER_LDT_ENTRIES); /新建一个LDT选择子ldtSelector = Selector(KERNEL_PRIVILEGE, true, Get_Descriptor_Index(UserContext-ldtDescriptor); /新建一个文本段描述符
10、 Init_Code_Segment_Descriptor( &UserContext-ldt0, (ulong_t) UserContext-memory, size / PAGE_SIZE, USER_PRIVILEGE ); /新建一个数据段 Init_Data_Segment_Descriptor(ldt1, /新建数据段和文本段选择子csSelector = Selector(USER_PRIVILEGE, false, 0);dsSelector = Selector(USER_PRIVILEGE, false, 1); /将引用数清0refCount = 0; return Us
11、erContext;fail:= 0) if (UserContext-memory ! Free(UserContext-memory); Free(UserContext);-/摧毁用户上下文void Destroy_User_Context(struct User_Context* userContext)Destroy a User_Context /释放占用的LDT Free_Segment_Descriptor(userContext-ldtDescriptor); userContext-ldtDescriptor=0; /释放内存空间 Free(userContext-memo
12、ry=0; /释放userContext本身占用的内存 Free(userContext); userContext=0;-int Load_User_Program(char *exeFileData,ulong_t exeFileLength,struct Exe_Format *exeFormat,const char *command,struct User_Context *pUserContext)Load a user executable into a user memory space using segmentation ulong_t maxva = 0;/要分配的最大内
13、存空间 unsigned numArgs;/进程数目 ulong_t argBlockSize;/参数块的大小 ulong_t size, argBlockAddr;/参数块地址 /计算用户态进程所需的最大内存空间 for (i = 0; i segmentListi; ulong_t topva = segment-startAddress + segment-sizeInMemory; /* FIXME: range check */ if (topva maxva) maxva = topva; Get_Argument_Block_Size(command, &numArgs, &ar
14、gBlockSize);/获取参数块信息 size = Round_Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE; argBlockAddr = size; size += argBlockSize; userContext = Create_User_Context(size);/按相应大小创建一个进程 if (userContext = 0)/如果为核心态进程 return -1; struct Exe_Segment *segment = & /根据段信息将用户程序中的各段内容复制到分配的用户内存空间 memcpy(userContext-mem
15、ory + segment-startAddress, exeFileData + segment-offsetInFile,segment-lengthInFile); /格式化参数块 Format_Argument_Block(userContext-memory + argBlockAddr, numArgs, argBlockAddr, command); /初始化数据段,堆栈段及代码段信息entryAddr = exeFormat-entryAddr;argBlockAddr = argBlockAddr;stackPointerAddr = argBlockAddr; /将初始化完
16、毕的User_Context赋给*pUserContext *pUserContext = userContext;/成功/将用户态的进程复制到内核缓冲区bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t bufSize) struct User_Context * UserContext = g_currentThread- /-: check if memory if validated if (!Validate_User_Memory(UserContext,srcInUser, bufSize) ret
17、urn false; memcpy(destInKernel, UserContext-memory + srcInUser, bufSize); return true;-/将内核态的进程复制到用户态bool Copy_To_User(ulong_t destInUser, void* srcInKernel, ulong_t bufSize)Validate_User_Memory(UserContext, destInUser, bufSize) memcpy(UserContext-memory + destInUser, srcInKernel, bufSize);-/切换到用户地址
18、空间void Switch_To_Address_Space(struct User_Context *userContext) ushort_t ldtSelector= 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* kthrea
19、d, struct User_Context* userContext) ulong_t eflags = EFLAGS_IF; unsigned csSelector=userContext-csSelector;/CS选择子 unsigned dsSelector=userContext-dsSelector;/DS选择子 Attach_User_Context(kthread, userContext); /初始化用户态进程堆栈,使之看上去像刚被中断运行一样 /分别调用Push函数将以下数据压入堆栈 Push(kthread, dsSelector); /数据选择子 Push(kthre
20、ad, userContext-stackPointerAddr); /堆栈指针 Push(kthread, eflags); /Eflags Push(kthread, csSelector); /文本选择子entryAddr); /程序计数器 Push(kthread, 0); /错误代码(0) /中断号(0) /初始化通用寄存单元,将ESI用户传递参数块地址 /* eax */ /* ebx */ /* edx */argBlockAddr); /* esi */ /* edi */ /* ebp */ /初始化数据段寄存单元 /* ds */ /* es */ /* fs */ /*
21、gs */开始用户进程struct Kernel_Thread* Start_User_Thread(struct User_Context* userContext, bool detached) struct Kernel_Thread* kthread = Create_Thread(PRIORITY_USER, detached); if (kthread ! Setup_User_Thread(kthread, userContext); Make_Runnable_Atomic(kthread); return kthread;= syscall.c =/需在此文件别的函数前增加一
22、个函数,函数名为Copy_User_String,它被函数Sys_PrintString调用,具体实现如下:static int Copy_User_String(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;Copy_From_User(str, uaddr, len) /从用户空间中复制数据 rc = EINVALID; Free(str); strlen = ; /成功 *pStr = str;static int Sys_Exit(struct Interrupt_State* st
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1