計算機(jī)操作系統(tǒng)實驗_運(yùn)行用戶態(tài)程序_第1頁
計算機(jī)操作系統(tǒng)實驗_運(yùn)行用戶態(tài)程序_第2頁
計算機(jī)操作系統(tǒng)實驗_運(yùn)行用戶態(tài)程序_第3頁
計算機(jī)操作系統(tǒng)實驗_運(yùn)行用戶態(tài)程序_第4頁
計算機(jī)操作系統(tǒng)實驗_運(yùn)行用戶態(tài)程序_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、西北工業(yè)大學(xué) 操作系統(tǒng)實驗 實驗報告一、實驗?zāi)康恼莆赵贕eekOS系統(tǒng)用戶態(tài)模式下加載并運(yùn)行可執(zhí)行程序的方法。二、實驗要求1. 按照實驗講義P127頁中的設(shè)計要求,實現(xiàn)在用戶態(tài)模式下加載并運(yùn)行可執(zhí)行程序的代碼,給出關(guān)鍵函數(shù)的代碼以及實驗結(jié)果。三、實驗過程及結(jié)果答:核心函數(shù)代碼如下:= user.c =/產(chǎn)生一個進(jìn)程(用戶態(tài))int Spawn(const char *program, const char *command, struct Kernel_Thread *pThread)/TODO("Spawn a process by reading an executable fr

2、om 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", p

3、rogram);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&quo

4、t;);goto fail;/在堆分配方式下釋放內(nèi)存并再次初始化exeFileDataFree(exeFileData);exeFileData = 0;/* 開始用戶進(jìn)程,調(diào)用Start_User_Thread函數(shù)創(chuàng)建一個進(jìn)程并使其進(jìn)入準(zhǔn)備運(yùn)行隊列*/process = Start_User_Thread(userContext, false);if (process != 0) KASSERT(process->refCount = 2);/* 返回核心進(jìn)程的指針 */*pThread = process; rc = process->pid;/記錄當(dāng)前進(jìn)程的ID elserc

5、 = ENOMEM;return rc;fail: /如果新進(jìn)程創(chuàng)建失敗則注銷User_Context對象if (exeFileData != 0)Free(exeFileData);/釋放內(nèi)存if (userContext != 0)Destroy_User_Context(userContext);/銷毀進(jìn)程對象return rc;-/切換至用戶上下文void Switch_To_User_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state)static struct User_Context* s_cu

6、rrentUserContext; /* last user context used */extern int userDebug;struct User_Context* userContext = kthread->userContext;KASSERT(!Interrupts_Enabled();if (userContext = 0) /userContext為0表示此進(jìn)程為核心態(tài)進(jìn)程就不用切換地址空間return;if (userContext != s_currentUserContext) ulong_t esp0;/if (userDebug) Print("

7、A%pn", kthread);Switch_To_Address_Space(userContext);/為用戶態(tài)進(jìn)程時則切換地址空間esp0 = (ulong_t) kthread->stackPage) + PAGE_SIZE;/if (userDebug)/ Print("S%lxn", esp0);/* 新進(jìn)程的核心棧. */Set_Kernel_Stack_Pointer(esp0);/設(shè)置內(nèi)核堆棧指針/* New user context is active */s_currentUserContext = userContext; = elf

8、.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->phents

9、ize*head->phnum);KASSERT(head->entry%4=0);exeFormat->numSegments=head->phnum;exeFormat->entryAddr=head->entry;for(i=0;i<head->phnum;i+)exeFormat->segmentListi.offsetInFile=proHeader->offset;exeFormat->segmentListi.lengthInFile=proHeader->fileSize;exeFormat->seg

10、mentListi.startAddress=proHeader->vaddr;exeFormat->segmentListi.sizeInMemory=proHeader->memSize;exeFormat->segmentLtFlags=proHeader->flags;proHeader+;return 0;= userseg.c =/需在此文件各函數(shù)前增加一個函數(shù),此函數(shù)的功能是按給定的大小創(chuàng)建一個用戶級進(jìn)程上下文,具體實現(xiàn)如下:/函數(shù)功能:按給定的大小創(chuàng)建一個用戶級進(jìn)程上下文static struct User_Context* Cre

11、ate_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); /為核心態(tài)進(jìn)程 else goto fail; /內(nèi)存為空 if (0 = UserContext->memory) goto fa

12、il; memset(UserContext->memory, '0', size); UserContext->size = size; /以下為用戶態(tài)進(jìn)程創(chuàng)建LDT(段描述符表) /新建一個LDT描述符 UserContext->ldtDescriptor = Allocate_Segment_Descriptor(); if (0 = UserContext->ldtDescriptor) goto fail; /初始化段描述符 Init_LDT_Descriptor(UserContext->ldtDescriptor, UserConte

13、xt->ldt, NUM_USER_LDT_ENTRIES); /新建一個LDT選擇子 UserContext->ldtSelector = Selector(KERNEL_PRIVILEGE, true, Get_Descriptor_Index(UserContext->ldtDescriptor); /新建一個文本段描述符 Init_Code_Segment_Descriptor( &UserContext->ldt0, (ulong_t) UserContext->memory, size / PAGE_SIZE, USER_PRIVILEGE )

14、; /新建一個數(shù)據(jù)段 Init_Data_Segment_Descriptor( &UserContext->ldt1, (ulong_t) UserContext->memory, size / PAGE_SIZE, USER_PRIVILEGE ); /新建數(shù)據(jù)段和文本段選擇子 UserContext->csSelector = Selector(USER_PRIVILEGE, false, 0); UserContext->dsSelector = Selector(USER_PRIVILEGE, false, 1); /將引用數(shù)清0 UserContex

15、t->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* userContext) /TODO("Destroy a User_Context"); /釋放占用的LDT Free_Segment_Descrip

16、tor(userContext->ldtDescriptor); userContext->ldtDescriptor=0; /釋放內(nèi)存空間 Free(userContext->memory); userContext->memory=0; /釋放userContext本身占用的內(nèi)存 Free(userContext); userContext=0;-int Load_User_Program(char *exeFileData,ulong_t exeFileLength,struct Exe_Format *exeFormat,const char *command,

17、struct User_Context *pUserContext) /TODO("Load a user executable into a user memory space using segmentation");int i;ulong_t maxva = 0;/要分配的最大內(nèi)存空間unsigned numArgs;/進(jìn)程數(shù)目ulong_t argBlockSize;/參數(shù)塊的大小ulong_t size, argBlockAddr;/參數(shù)塊地址struct User_Context *userContext = 0;/計算用戶態(tài)進(jìn)程所需的最大內(nèi)存空間for (i

18、= 0; i < exeFormat->numSegments; +i) /elf.hstruct 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, &argBlockS

19、ize);/獲取參數(shù)塊信息size = Round_Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE;argBlockAddr = size;size += argBlockSize;userContext = Create_User_Context(size);/按相應(yīng)大小創(chuàng)建一個進(jìn)程if (userContext = 0)/如果為核心態(tài)進(jìn)程return -1;for (i = 0; i < exeFormat->numSegments; +i) struct Exe_Segment *segment = &exeFormat->

20、;segmentListi;/根據(jù)段信息將用戶程序中的各段內(nèi)容復(fù)制到分配的用戶內(nèi)存空間memcpy(userContext->memory + segment->startAddress, exeFileData + segment->offsetInFile,segment->lengthInFile);/格式化參數(shù)塊Format_Argument_Block(userContext->memory + argBlockAddr, numArgs, argBlockAddr, command);/初始化數(shù)據(jù)段,堆棧段及代碼段信息userContext->e

21、ntryAddr = exeFormat->entryAddr;userContext->argBlockAddr = argBlockAddr;userContext->stackPointerAddr = argBlockAddr;/將初始化完畢的User_Context賦給*pUserContext*pUserContext = userContext;return 0;/成功-/將用戶態(tài)的進(jìn)程復(fù)制到內(nèi)核緩沖區(qū)bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t bufSize) struc

22、t User_Context * UserContext = g_currentThread->userContext;/-: check if memory if validatedif (!Validate_User_Memory(UserContext,srcInUser, bufSize)return false;memcpy(destInKernel, UserContext->memory + srcInUser, bufSize); return true;-/將內(nèi)核態(tài)的進(jìn)程復(fù)制到用戶態(tài)bool Copy_To_User(ulong_t destInUser, voi

23、d* srcInKernel, ulong_t bufSize)struct 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 Use

24、r_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 <geekos/user.h>-/創(chuàng)建一個用戶進(jìn)程/*static*/ void Setup_User_Thread(struct Kernel_Thread*

25、 kthread, struct User_Context* userContext) ulong_t eflags = EFLAGS_IF; unsigned csSelector=userContext->csSelector;/CS選擇子 unsigned dsSelector=userContext->dsSelector;/DS選擇子 Attach_User_Context(kthread, userContext);/初始化用戶態(tài)進(jìn)程堆棧,使之看上去像剛被中斷運(yùn)行一樣/分別調(diào)用Push函數(shù)將以下數(shù)據(jù)壓入堆棧 Push(kthread, dsSelector); /數(shù)據(jù)選

26、擇子 Push(kthread, userContext->stackPointerAddr); /堆棧指針 Push(kthread, eflags); /Eflags Push(kthread, csSelector); /文本選擇子 Push(kthread, userContext->entryAddr); /程序計數(shù)器 Push(kthread, 0); /錯誤代碼(0) Push(kthread, 0); /中斷號(0) /初始化通用寄存單元,將ESI用戶傳遞參數(shù)塊地址 Push(kthread, 0); /* eax */ Push(kthread, 0); /* e

27、bx */ Push(kthread, 0); /* edx */ Push(kthread, 0); /* edx */ Push(kthread, userContext->argBlockAddr); /* esi */ Push(kthread, 0); /* edi */ Push(kthread, 0); /* ebp */ /初始化數(shù)據(jù)段寄存單元 Push(kthread, dsSelector); /* ds */ Push(kthread, dsSelector); /* es */ Push(kthread, dsSelector); /* fs */ Push(kt

28、hread, dsSelector); /* gs */ /開始用戶進(jìn)程struct Kernel_Thread* Start_User_Thread(struct User_Context* userContext, 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; =

29、syscall.c =/需在此文件別的函數(shù)前增加一個函數(shù),函數(shù)名為Copy_User_String,它被函數(shù)Sys_PrintString調(diào)用,具體實現(xiàn)如下: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; got

30、o fail; if (!Copy_From_User(str, uaddr, len) /從用戶空間中復(fù)制數(shù)據(jù) rc = EINVALID; Free(str); goto fail; strlen = '0' /成功 *pStr = str;fail: return rc;-static int Sys_Exit(struct Interrupt_State* state)Exit(state->ebx);-static int Sys_PrintString(struct Interrupt_State* state)int rc = 0;/返回值uint_t le

31、ngth = state->ecx;/字符串長度uchar_t* buf = 0;if (length > 0) if (rc = Copy_User_String(state->ebx, length, 1023, (char*) &buf) != 0)goto done;Put_Buf(buf, length);done:if (buf != 0)Free(buf);return rc;-static int Sys_GetKey(struct Interrupt_State* state) return Wait_For_Key(); /返回按鍵碼keyboar

32、d.c/Wait_For_Key()-static int Sys_SetAttr(struct Interrupt_State* state) Set_Current_Attr(uchar_t) state->ebx);return 0;-static int Sys_GetCursor(struct Interrupt_State* state) int row, col;Get_Cursor(&row, &col);if (!Copy_To_User(state->ebx, &row, sizeof(int) |!Copy_To_User(state-

33、>ecx, &col, sizeof(int)return -1;return 0;-static int Sys_PutCursor(struct Interrupt_State* state) return Put_Cursor(state->ebx, state->ecx) ? 0 : -1;-static int Sys_Spawn(struct Interrupt_State* state) int rc; /函數(shù)返回值 char *program = 0; /進(jìn)程名稱 char *command = 0; /用戶命令struct Kernel_Thread

34、 *process;if (rc = Copy_User_String(state->ebx, state->ecx, VFS_MAX_PATH_LEN, &program) != 0)goto fail;if(rc = Copy_User_String(state->edx, state->esi, 1023, &command) != 0)/從用戶空間復(fù)制用戶命令goto fail;Enable_Interrupts(); /開中斷rc = Spawn(program, command, &process);/得到進(jìn)程名稱和用戶命令后便可生成

35、一個新進(jìn)程if (rc = 0) /若成功則返回新進(jìn)程ID號KASSERT(process != 0);rc = process->pid;Disable_Interrupts();/關(guān)中斷fail:/返回小于0的錯誤代碼if (program != 0)Free(program);if (command != 0)Free(command);return rc;-static int Sys_Wait(struct Interrupt_State* state) /TODO("Wait system call");int exitCode;struct Kernel

36、_Thread *kthread = Lookup_Thread(state->ebx);if (kthread = 0)return -12;Enable_Interrupts();exitCode = Join(kthread);Disable_Interrupts();return exitCode;-static int Sys_GetPID(struct Interrupt_State* state) /TODO("GetPID system call");return g_currentThread->pid;= main.c =static void Spawn_Init_Process(void) /TODO("Spawn the init process"); struct Kernel_Thread *pThread; Spawn("/c/shell.exe","/c/shell.exe",&pThread);實驗結(jié)果如圖所示:原理:Geekos 提供了一個簡單的shell,保存在PFAT文件系統(tǒng)內(nèi),所以geekos系統(tǒng)啟動后,啟動shell程序/c/shell.exe運(yùn)行,將/c/shell.exe作為可執(zhí)行文件傳遞給spawn函數(shù)的progra

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論