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

下載本文檔

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

文檔簡(jiǎn)介

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

2、system); int rc;char *exeFileData = 0;ulong_t exeFileLe ngth;struct User_C on text *userC on text = 0;struct Kern el_Thread *process = 0;struct Exe_Format exeFormat;if (rc = Read_Fully(program, (void*) & exeFileData, & exeFileLe ngth) != 0 )Print(Failed to Read File %s!n, program);goto fail;if(rc =

3、Parse_ELF_Executable(exeFileData, exeFileLe ngth, &exeFormat) != 0 )Prin t(Failed to Parse ELF File!n ”);goto fail;if(rc = Load_User_Program(exeFileData, exeFileLe ngth, &exeFormat, mand, & userC on text) != 0)Prin t(Failed to Load User Program!n);goto fail;/在堆分配方式下釋放內(nèi)存并再次初始化exeFileDataFree(exeFileD

4、ata);exeFileData = 0;/*開(kāi)始用戶進(jìn)程,調(diào)用Start_User_Thread函數(shù)創(chuàng)建一個(gè)進(jìn)程并使其進(jìn)入準(zhǔn)備運(yùn)行隊(duì)列*/process = Start_User_Thread(userC on text, false);if (process != 0) KASSERT(process-refCou nt = 2);/*返回核心進(jìn)程的指針*/*pThread = process;rc = process-pid;記錄當(dāng)前進(jìn)程的IDelserc = ENOMEM;return rc;fail: /如果新進(jìn)程創(chuàng)建失敗如此注銷(xiāo)User_Context對(duì)象if (exeFileDa

5、ta != 0)Free(exeFileData);/ 釋放內(nèi)存if (userCo ntext != 0)Destroy_User_Context(userContext);/ 銷(xiāo)毀進(jìn)程對(duì)象return rc; /切換至用戶上下文void Switch_To_User_C on text(structKernel_Thread* kthread, struct In terrupt_State*state)static struct User_C on text* s_curre ntUserC on text; /* last user con text used */exter n in

6、t userDebug;struct User_C on text* userC on text = kthread-userC on text;KASSERT(!I nterrupts_E nabled();if (userCo ntext = 0) /userC on text為0表示此進(jìn)程為核心態(tài)進(jìn)程就不用切換地址空間return;if (userC on text != s_curre ntUserC on text) ulong_t esp0;/if (userDebug) Prin t(A%pn, kthread);Switch_To_Address_Space(userConte

7、xt);/為用戶態(tài)進(jìn)程時(shí)如此切換地址空間esp0 = (ulo ng_t) kthread-stackPage) + PAGE_SIZE;/if (userDebug)/ Prin t(S%lxn, esp0);/*新進(jìn)程的核心棧 */Set_Kernel_Stack_Poi nter(espO);/ 設(shè)置內(nèi)核堆棧指針/* New user con text is active */s_curre ntUserC on text = userC on text;= elf.c =int Parse_ELF_Executable(char *exeFileData, ulong_t exeFil

8、eLength, struct Exe_Format *exeFormat)int i;elfHeader *head=(elfHeader*)exeFileData;programHeader *proHeader=(programHeader *)(exeFileData+head-phoff);KASSERT(exeFileData!=NULL);KASSERT(exeFileLe ngthhead-ehsize+head-phe ntsize*head-ph nu m);KASSERT(head-e ntry%4=0);exeFormat-nu mSegme nts=head-ph n

9、um;exeFormat-e ntryAddr=head-e ntry;for(i=0;iph nu m;i+)exeFormat-segme ntListi.offset InF ile=proHeader-offset;exeFormat-segme ntListien gthI nFile=proHeader-fileSize;exeFormat-segme ntListi.startAddress=proHeader-vaddr;exeFormat-segme ntListi.sizel nM emory=proHeader-memSize;exeFormat-segme ntList

10、tFlags=proHeader-flags;proHeader+;return 0;= userseg.c =需在此文件各函數(shù)前增加一個(gè)函數(shù),此函數(shù)的功能是按給定的大小創(chuàng)建一個(gè)用戶級(jí)進(jìn)程上下文,具體實(shí)現(xiàn)如下:函數(shù)功能:按給定的大小創(chuàng)建一個(gè)用戶級(jí)進(jìn)程上下文static struct User_C on text* Create_User_C on text(u long_t size)struct User_C on text * UserC on text;size = Roun d_Up_To_Page(size);UserCo ntext = (struct User_Co n

11、text *)Malloc(sizeof(struct User_Co ntext);if (UserCo ntext != 0)UserC on text-memory = Malloc(size);/為核心態(tài)進(jìn)程elsegoto fail;內(nèi)存為空if (0 = UserC on text-memory)goto fail;memset(UserC on text-memory, 0, size);UserC on text-size = size;/以下為用戶態(tài)進(jìn)程創(chuàng)建LDT(段描述符表)新建一個(gè)LDT描述符UserC on text-ldtDescriptor = Allocate_S

12、egme nt_Descriptor();if (0 = UserC on text-ldtDescriptor)goto fail;/初始化段描述符In it_LDT_Descriptor(UserCo ntext-ldtDescriptor,UserCo ntext-ldt,NUM_USER_LDT_ENTRIES);新建一個(gè)LDT選擇子UserCo ntext-ldtSelector=Selector(KERNEL_PRIVILEGE,true,Get_Descriptor_I ndex(UserC on text-ldtDescriptor);/新建一個(gè)文本段描述符Ini t_Code

13、_Segme nt_Descriptor(& UserCo ntext-ldt0,(ulon g_t) UserC on text-memory,size / PAGE_SIZE,USER_PRIVILEGE);/新建一個(gè)數(shù)據(jù)段Ini t_Data_Segme nt_Descriptor(& UserCo ntext-ldt1,(ulon g_t) UserC on text-memory,size / PAGE_SIZE,USER_PRIVILEGE);/新建數(shù)據(jù)段和文本段選擇子UserC on text-csSelector = Selector(USER_PRIVILEGE, false

14、, 0);UserCo ntext-dsSelector = Selector(USER_PRIVILEGE, false, 1);/將引用數(shù)清0UserC on text-refCou nt = 0;retur n UserC on text;fail:if (UserCo ntext != 0)if (UserC on text-memory != 0)Free(UserC on text-memory);Free(UserC on text);return 0; /摧毀用戶上下文void Destroy_User_C on text(struct User_C on text* user

15、C on text) TODO(Destroy a User_Co ntext);/釋放占用的LDTFree_Segme nt_Descriptor(userC on text-ldtDescriptor);userC on text-ldtDescriptor=0;/釋放內(nèi)存空間Free(userC on text-memory); userC on text-memory=0;/釋放userContext本身占用的內(nèi)存Free(userC on text);userC on text=0;int Load_User_Program(char *exeFileData,u long_texe

16、FileLe ngth,structExe_Format*exeFormat,c onst char *ma nd,struct User_C on text *pUserC on text)TODO(Load a user executable into a user memory space using segme ntati on ”);int i;ulong_t maxva = 0;/要分配的最大內(nèi)存空間un sig ned nu mArgs;/ 進(jìn)程數(shù)目ulong_t argBlockSize;/ 參數(shù)塊的大小ulong_t size, argBlockAddr;/ 參數(shù)塊地址str

17、uct User_C on text *userC on text = 0;/計(jì)算用戶態(tài)進(jìn)程所需的最大內(nèi)存空間for (i = 0; i nu mSegme nts; +i) struct Exe_Segme nt *segme nt = & exeFormat-segme ntListi;ulong_t topva = segme nt-startAddress + segme nt-sizel nM emory; /* FIXME: range check */if (topva maxva)maxva = topva;Get_Argume nt_Block_Size(ma nd, &nu

18、 mArgs, &argBlockSize); 獲取參數(shù)塊信息size = Round_ Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE;argBlockAddr = size;size += argBlockSize;userContext = Create_User_Context(size);/ 按相應(yīng)大小創(chuàng)建一個(gè)進(jìn)程if (userContext = 0)/如果為核心態(tài)進(jìn)程return -1;for (i = 0; i nu mSegme nts; +i) struct Exe_Segme nt *segme nt = & exeFormat-s

19、egme ntListi;/根據(jù)段信息將用戶程序中的各段內(nèi)容復(fù)制到分配的用戶內(nèi)存空間memcpy(userC on text-memory+segme nt-startAddress,exeFileData +segme nt-offsetl nFile,segme nt-le ngthl nFile);/格式化參數(shù)塊Format_Argume nt_Block(userC on text-memory+ argBlockAddr, nu mArgs, argBlockAddr,man d);/初始化數(shù)據(jù)段,堆棧段與代碼段信息userC on text-e ntryAddr = exeForm

20、at-e ntryAddr;userC on text-argBlockAddr = argBlockAddr;userC on text-stackPoi nterAddr = argBlockAddr;將初始化完畢的 User_Context賦給*pUserContext *pUserC on text = userC on text;return 0;/ 成功 /將用戶態(tài)的進(jìn)程復(fù)制到內(nèi)核緩沖區(qū)bool Copy_From_User(void* dest InKern el, ulong_t srcInU ser, ulong_t bufSize) struct User_C on tex

21、t * UserC on text = g_curre ntThread-userC on text;/-: check if memory if validatedif (!Validate_User_Memory(UserCo ntext,srcl nU ser, bufSize)return false;memcpy(destl nKern el, UserC on text-memory + srcInU ser, bufSize);return true; /將內(nèi)核態(tài)的進(jìn)程復(fù)制到用戶態(tài)bool Copy_To_User(u long_t destl nU ser, void* src

22、InKern el, ulong_t bufSize) struct User_C on text * UserC on text = g_curre ntThread-userC on text;if (!Validate_User_Memory(UserCo ntext, destI nU ser,bufSize)return false;memcpy(UserC on text-memory + destI nU ser, srcInKern el, bufSize); return true; /切換到用戶地址空間void Switch_To_Address_Space(struct

23、User_C on text *userC on text)ushort_t ldtSelector= userC on text-ldtSelector;/* Switch to the LDT of the new user con text */_asmvolatile_ (lldt %0:a(ldtSelector);= kthread.c =添加頭文件 #i nclude /創(chuàng)建一個(gè)用戶進(jìn)程/*static*/ void Setup_User_Thread(struct Kern el_Thread* kthread, struct User_C on text* userC on

24、text)ulo ng_t eflags = EFLAGS_IF;unsigned csSelector=userContext-csSelector;/CS 選擇子unsigned dsSelector=userContext-dsSelector;/DS 選擇子Attach_User_C on text(kthread, userC on text);初始化用戶態(tài)進(jìn)程堆棧,使之看上去像剛被中斷運(yùn)行一樣分別調(diào)用Push函數(shù)將以下數(shù)據(jù)壓入堆棧Push (kthread, dsSelector);Push(kthread, userC on text-stackPo in terAddr);Pu

25、sh(kthread, eflags);Push(kthread, csSelector);Push(kthread, userC on text-e ntryAddr);Push (kthread, 0);Push (kthread, 0);/數(shù)據(jù)選擇子堆棧指針/Eflags文本選擇子/程序計(jì)數(shù)器錯(cuò)誤代碼(0)中斷號(hào)(0)/初始化通用存放單元,將ESI用戶傳遞參數(shù)塊地址Push(kthread, 0); /* eax */Push(kthread, 0); /* ebx */Push(kthread, 0); /* edx */Push(kthread, 0); /* edx */Push(

26、kthread, userC on text-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(kthread, dsSelector); /* gs */開(kāi)始用戶進(jìn)程struct Kern el_Thread* Start_User_Thread(st

27、ruct User_C on text* userC on text, bool detached) struct Kernel_Thread* kthread = Create_Thread(PRIORITY_USER, detached);if (kthread != 0)Setup_User_Thread(kthread, userC on text);Make_Ru nn able_Atomic(kthread);return kthread;syscall.c/需在此文件別的函數(shù)前增加一個(gè)函數(shù),函數(shù)名為Copy_User_String ,它被函數(shù)Sys_PrintString調(diào)用,具

28、體實(shí)現(xiàn)如下:static int Copy_User_Stri ng(u long_t uaddr, ulon g_t le n, ulong_t maxLe n, char *pStr) int rc = 0;char *str;if (le n maxLe n)/超過(guò)最大長(zhǎng)度return EINV ALID;str = (char*) Malloc(le n+1);/ 為字符串分配空間if (0 = str)rc = ENOMEM;goto fail;if (!Copy_From_User(str, uaddr, le n)從用戶空間中復(fù)制數(shù)據(jù)rc = EINV ALID;Free(str

29、);goto fail;strle n = 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 length = state-ecx;/ 字符串長(zhǎng)度uchar_t* buf = 0;if (le ngth 0) if (rc = Copy_User_String(state-ebx, le

30、ngth, 1023, (char*) &buf) != 0) goto done;Put_Buf(buf, le ngth);done:if (buf != 0)Free(buf);return rc; static int Sys_GetKey(struct Interrupt_State* state)return Wait_For_Key(); / 返回按鍵碼 keyboard.c/Wait_For_Key() static int Sys_SetAttr(struct In terrupt_State* state) Set_Curre nt_Attr(uchar_t) state-

31、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( in t) |!Copy_To_User(state-ecx, &col, sizeof( in t) return -1;return 0; static int Sys_PutCursor(struct Interrupt_State* state) retur n Put_Cursor(st

32、ate-ebx, state-ecx) ? 0 : -1; static int Sys_Spaw n( struct In terrupt_State* state)int rc;/函數(shù)返回值char *program = 0;進(jìn)程名稱char *ma nd = 0;/ 用戶命令struct Kern el_Thread *process;if (rc = Copy_User_Stri ng(state-ebx, state-ecx, VFS_MAX_PATH_LEN, & program) != 0) goto fail;if(rc = Copy_User_Stri ng(state-ed

33、x, state-esi, 1023, &man d) != 0)/從用戶空間復(fù)制用戶命令goto fail;En able_I nterrupts();/ 開(kāi)中斷rc = Spawn(program, mand, &process);/得到進(jìn)程名稱和用戶命令后便可生成一個(gè)新進(jìn)程if (rc = 0) /假如成功如此返回新進(jìn)程 ID號(hào)KASSERT(process != 0);rc = process-pid;Disable_Interrupts();/ 關(guān)中斷if (program != 0) Free(program);if (ma nd != 0)Free(ma nd); return

34、rc; static int Sys_Wait(struct Interrupt_State* state) /TODO(Wait system call);int exitCode;struct Kernel_Thread *kthread = Lookup_Thread(state-ebx); if (kthread = 0)return -12;En able_I nterrupts();exitCode = Join( kthread);Disable_I nterrupts();retur n exitCode; static int Sys_GetPID(struct Interr

35、upt_State* state) /TODO(GetPID system call);retur n g_curre ntThread-pid;= main.c = static void Spaw n_lni t_Process(void) /TODO(Spaw n the in it process);struct Kernel_Thread *pThread;Spaw n(”/c/shell.exe,/c/shell.exe,&pThread);實(shí)驗(yàn)結(jié)果如下列圖:C Q dcKhs xB6 emulator, http:;/bochs.sourceforgcnetit- .| | ji

36、iTsijiirercWiSrfcgI ist 1G48E7G bytes in kernEi Jheapkry br)Ard .DHA Caintpoller.-. Cloppy contro1ier.06, hcods2, sectors 18IEE duh tibuller.1333313333 H |jlL,frZl. . FI7TTk35 *|躥% 廉遜緩空,5.航*通耳百ij原理:Geekos提供了一個(gè)簡(jiǎn)單的shell,保存在PFAT文件系統(tǒng)內(nèi),所以geekos系統(tǒng)啟動(dòng)后,啟動(dòng)shell程序/c/shell.exe運(yùn)行,將作為可執(zhí)行文件傳遞給spawn函數(shù)的program參數(shù),創(chuàng)建第一個(gè)用戶態(tài)進(jìn)程,然后由它來(lái)創(chuàng)建其他進(jìn)程。運(yùn)行后,geekos就可以掛在這shell,并能運(yùn)行測(cè)試文件c.exe和b.exeo四、實(shí)驗(yàn)分析GeekOS系統(tǒng)最早創(chuàng)建的內(nèi)核進(jìn)程有Idle、Reaper和Main三個(gè)進(jìn)程,它們 由Ini t

溫馨提示

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

評(píng)論

0/150

提交評(píng)論