操作系統(tǒng)課設報告桂林電子科技大學_第1頁
操作系統(tǒng)課設報告桂林電子科技大學_第2頁
操作系統(tǒng)課設報告桂林電子科技大學_第3頁
操作系統(tǒng)課設報告桂林電子科技大學_第4頁
操作系統(tǒng)課設報告桂林電子科技大學_第5頁
已閱讀5頁,還剩21頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、桂林電子科技大學綜合設計說明書用紙GeekOSGeekOS 操作系統(tǒng)操作系統(tǒng)課程設計說明書課程設計說明書題題 目:目: GeekOSGeekOS 操作系統(tǒng)的研究與實驗操作系統(tǒng)的研究與實驗 學學 院:院: 計算機科學與工程學院計算機科學與工程學院 專專 業(yè)業(yè): 信息安全信息安全 姓姓 名名: 學 號: 指導教師:指導教師: 2015 年年 06 月月 12 日日桂林電子科技大學綜合設計說明書用紙目 錄1 GEEKOS 簡介簡介 .11.1 GEEKOS 系統(tǒng)源代碼結(jié)構(gòu).12 課程設計環(huán)境課程設計環(huán)境 .23 項目項目 0 的設計實現(xiàn)的設計實現(xiàn) .33.1 項目設計目的 .33.2 項目設計要求.

2、33.3 項目實現(xiàn)原理.33.4 項目實現(xiàn)過程.33.5 運行結(jié)果.54 項目項目 1 的設計實現(xiàn)的設計實現(xiàn) .64.1 項目設計目的 .64.2 項目設計要求.64.3 項目實現(xiàn)原理 .64.4 項目實現(xiàn)過程 .84.5 運行結(jié)果.95 項目項目 2 的設計實現(xiàn)的設計實現(xiàn) .105.1 項目設計目的 .105.2 項目設計目的 .105.3 項目實現(xiàn)原理 .115.4 項目實現(xiàn)過程 .135.5 運行結(jié)果 .236 遇到問題及解決方法遇到問題及解決方法 .237 課程設計總結(jié)課程設計總結(jié) .24桂林電子科技大學綜合設計說明書用紙 第 1 頁 1 GeekOS 簡介GeekOS 是一個基于 X

3、86 架構(gòu)的 PC 上運行的微操作系統(tǒng)內(nèi)核,由美國馬理蘭大學的教師開發(fā),主要用于操作系統(tǒng)課程設計,目的是使學生能夠?qū)嶋H動手參與到一個操作系統(tǒng)的開發(fā)工作中。出于教學目的,這個系統(tǒng)內(nèi)核設計簡單,卻又兼?zhèn)鋵嵱眯?,它可以運行在真正的 X86 PC 硬件平臺。作為一個課程設計平臺,GeekOS 由一個基本的操作系統(tǒng)內(nèi)核作為基礎,提供了操作系統(tǒng)與硬件之間的所有必備接口,實現(xiàn)了系統(tǒng)引導,實模式到保護模式的轉(zhuǎn)換,中斷調(diào)用及異常處理,基于段式的內(nèi)存管理,FIFO 進程調(diào)度算法以及內(nèi)核進程,基本的輸入輸出(鍵盤作為輸入設備,顯示器作為輸出設備),以及一個用于存放用戶程序的只讀文件系統(tǒng)PFAT。學生可以在 Linu

4、x 或 Unix 環(huán)境下對其進行功能擴充,且其針對進程、文件系統(tǒng)、存儲管理等操作系統(tǒng)核心內(nèi)容分別設計了 7 個難度逐漸增加的項目供學生選擇 。1.1 GeekOS 系統(tǒng)源代碼結(jié)構(gòu)GeekOS 操作系統(tǒng)源文件 geekos-0.3.0.zip 可以從 http:/下載。圖 1.1 GeekOS 系統(tǒng)主目錄在 doc 目錄里的文件 hacking.pdf 和 index.htm 是 GeekOS 系統(tǒng)的參考文檔。Scripts目錄下有 startProject 和 removeEmptyConflicts 兩個腳本文件。GeekOS 系統(tǒng)的源文件在src 目錄下,分為 7 個項目:Project0

5、 到 Project7。在 build 文件夾中,包含系統(tǒng)編譯后的可執(zhí)行文件的文件、軟盤鏡像或是硬盤鏡像、makefile 項目管理文件。在 include 文件夾中有 GeekOS 和 libc 兩個子目錄,在 GeekOS 子目錄中有 kthread.h、keyboard.h 等文件。桂林電子科技大學綜合設計說明書用紙 第 2 頁 圖 1.2 項目文件結(jié)構(gòu)圖2 課程設計環(huán)境1. 虛擬機軟件:VMware Workstation 10.0。2. 虛擬系統(tǒng):linux 系統(tǒng) CentOS 6.0。3. NASM 匯編器。4. GNU gcc 編譯器。5. GNU gdb 調(diào)試器。6. Sour

6、se Insight:程序編輯器和代碼瀏覽器。7. Bochs:GeekOS 運行于 Windows(或 Linux)下的 Bochs PC 模擬器,Bochs 是用 C+ 開發(fā)的可移植的 IA-32 (x86) PC 模擬器,它包括對 Intel x86 CPU 、通用 I/O 設備和可定制的 BIOS 的模擬,幾乎可以運行在所有流行的平臺上。在本次課設中使用的是 bochs 2.6。圖 2.1 課設環(huán)境桂林電子科技大學綜合設計說明書用紙 第 3 頁 3 項目 0 的設計實現(xiàn)3.1 項目設計目的熟悉 GeekOS 的項目編譯、調(diào)試和運行環(huán)境,掌握 GeekOS 運行工作過程。3.2 項目設計

7、要求1.搭建 GeekOS 的編譯和調(diào)試平臺,掌握 GeekOS 的內(nèi)核進程工作原理。2.熟悉鍵盤操作函數(shù),編程實現(xiàn)一個內(nèi)核進程。該進程的功能是:接收鍵盤輸入的字符并顯示到屏幕上,當輸入 ctrl+d 時,結(jié)束進程的運行。3.3 項目實現(xiàn)原理項目 0 主要要求設計一個函數(shù)對鍵盤的中斷進行響應。這主要通過使用 GeekOS 提供的鍵盤響應函數(shù) Wait_Kernel_Thread 進行鍵盤中斷的響應和返回鍵值。該函數(shù)首先檢查鍵盤緩沖區(qū)是否有按鍵,如果有,就讀取一個鍵碼,如果此時鍵盤緩沖區(qū)沒有鍵值,就將線程放入鍵盤事件等待隊列。于是可分為兩步完成:1.編寫函數(shù) EchoCount,函輸功能是:接受

8、鍵盤輸入的按鍵,并將鍵值顯示在顯示器,當輸入 Ctrl+D 退出。2.在 Main 函數(shù)體內(nèi)調(diào)用 Start_Kernel_Thread 函數(shù),將編寫的函數(shù)地址傳遞給startFunc,建立一個內(nèi)核進程。3.4 項目實現(xiàn)過程1.添加代碼(1)在 Main 函數(shù)中編寫一個函數(shù),函數(shù)功能是:接收鍵盤輸入的按鍵,并將鍵值顯示到顯示器的函數(shù),當輸入 Ctrl+D 就退出。void project0()Print(To Exit hit Ctrl + d.n); Keycode keycode; while(1) if( Read_Key(&keycode) ) /讀取鍵盤按鍵狀態(tài)if(!( (

9、keycode & KEY_SPECIAL_FLAG) | (keycode & KEY_RELEASE_FLAG) ) /只處理非特殊按鍵的按下事件 int asciiCode = keycode & 0 xff; /低 8 位為 Ascii 碼 if( (keycode & KEY_CTRL_FLAG)=KEY_CTRL_FLAG & asciiCode=d) /按下 Ctrl 鍵 Print(n-BYE!-n); Exit(1); else Print(%c,(asciiCode=r) ? n : keycode);桂林電子科技大學綜合設計說明書用

10、紙 第 4 頁 /放在 main 函數(shù)之前(2) 在 Main 函數(shù)體內(nèi)調(diào)用 Start_Kernel_Thread 函數(shù),將步驟 1 編寫的函數(shù)地址傳遞給參數(shù) startFunc,建立一個內(nèi)核級進程。 void Main(struct Boot_Info* bootInfo) /TODO(Start a kernel thread to echo pressed keys and print counts); struct Kernel_Thread *thread; thread = Start_Kernel_Thread(&project0,0,PRIORITY_NORMAL,f

11、alse); 2.編譯 GeekOS 項目 project0(1)shell# cd /geekos-0.3.0/src/project0/build(2)shell# make depend生成 depend.mak 文件。圖 3.1 make depend 執(zhí)行過程(3)shell# make成功之后在 build 目錄下生成 fd.img 文件。桂林電子科技大學綜合設計說明書用紙 第 5 頁 圖 3.2 make 執(zhí)行過程3.配置啟動 Bochs(1)創(chuàng)建 bochs 配置文件shell# gedit bochsrc(2)在編輯器中輸入一下配置內(nèi)容gdbstub: enabled=1,

12、port=1234, text_base=0, data_base=0, bss_base=0romimage:file=$BXSHARE/BIOS-bochs-latestmegs: 8boot: afloppya:1_44=fd.img, status=insertedlog: ./bochs.out(3)保存,直接退出 gedit3.5 運行結(jié)果(1)啟動 bochsshell# bochs - bochsrc(2)選擇 begin simulation(3)結(jié)果:桂林電子科技大學綜合設計說明書用紙 第 6 頁 圖 3.3 項目 0 運行結(jié)果4 項目 1 的設計實現(xiàn)4.1 項目設計目的熟

13、悉 ELF 文件格式,了解 GeekOS 系統(tǒng)如何將 ELF 格式的可執(zhí)行程序裝入到內(nèi)存,建立內(nèi)核進程并運行的實現(xiàn)技術(shù)。4.2 項目設計要求1.修改/geekos/elf.c 文件:在函數(shù) Parse_ELF_Executable( )中添加代碼,分析 ELF 格式的可執(zhí)行文件(包括分析得出 ELF 文件頭、程序頭,獲取可執(zhí)行文件長度,代碼段、數(shù)據(jù)段等信息) ,并填充 Exe_Format 數(shù)據(jù)結(jié)構(gòu)中的域值。2.在 Linux 環(huán)境下編譯系統(tǒng)得到 GeekOS 鏡像文件。3.編寫一個相應的 bochs 配置文件。4.在 bochs 中運行 GeekOS 系統(tǒng)顯示結(jié)果。4.3 項目實現(xiàn)原理1.E

14、LF 文件格式。連接程序視圖 執(zhí)行程序視圖 ELF 頭部ELF 頭部 程序頭部表(可選) 程序頭部表 節(jié)區(qū) 1 段 1 桂林電子科技大學綜合設計說明書用紙 第 7 頁 節(jié)區(qū) n 段 2 節(jié)區(qū)頭部表 節(jié)區(qū)頭部表(可選) 表 4.1 ELF 目標文件格式2. 內(nèi)存中的可執(zhí)行文件鏡像GeekOS 中的用戶進程全部在系統(tǒng)的編譯階段完成編譯和鏈接,形成可執(zhí)行文件,用戶可執(zhí)行文件保存在 PFAT 文件系統(tǒng)中。項目 1 要完成的事系統(tǒng)啟動后,從 PFAT 文件系統(tǒng)將可執(zhí)行文件裝入內(nèi)存,建立進程并運行得到相應的輸出。如下圖:圖 4.1 文件鏡像3. 內(nèi)核線程的建立流程該過程主要由 Spawner 函數(shù)實現(xiàn),其

15、主要經(jīng)過:調(diào)用 Read_Fully 函數(shù)將文件讀入內(nèi)存,后調(diào)用 Parse_ELF_Executable 函數(shù)分析 ELF 文件,最后調(diào)用 Spawn_Program 函數(shù)將可執(zhí)行程序的代碼段和數(shù)據(jù)段等裝入內(nèi)存,此后便可以開始運行一個內(nèi)核級進程了。如下圖:桂林電子科技大學綜合設計說明書用紙 第 8 頁 圖 4.2 建立流程4.4 項目實現(xiàn)過程1.添加代碼修改/geekos/elf.c 文件。在函數(shù) Parse_ELF_Executalbe()中添加代碼,分析 ELF 格式的可執(zhí)行文件(包括分析得出ELF 文件頭、程序頭,獲取可執(zhí)行文件長度,代碼段、數(shù)據(jù)段等信息) ,并填充 Exe_Forma

16、t數(shù)據(jù)結(jié)構(gòu)中的域值。int Parse_ELF_Executable(char *exeFileData, ulong_t exeFileLength, struct Exe_Format *exeFormat) /TODO(Parse an ELF executable image); int i; elfHeader *head=(elfHeader*)exeFileData; programHeader *proHeader=(programHeader *)(exeFileData+head-phoff); KASSERT(exeFileData!=NULL); KASSERT(exe

17、FileLengthhead-ehsize+head-phentsize*head-phnum); KASSERT(head-entry%4=0);桂林電子科技大學綜合設計說明書用紙 第 9 頁 exeFormat-numSegments=head-phnum; exeFormat-entryAddr=head-entry; for(i=0;iphnum;i+) exeFormat-segmentListi.offsetInFile=proHeader-offset; exeFormat-segmentListi.lengthInFile=proHeader-fileSize; exeForm

18、at-segmentListi.startAddress=proHeader-vaddr; exeFormat-segmentListi.sizeInMemory=proHeader-memSize; exeFormat-segmentLtFlags=proHeader-flags; proHeader+;return 0;2. 編譯 GeekOS 項目 project0(1)執(zhí)行 make dependshell# make depend生成 depend.mak 文件(2)執(zhí)行 makeshell# make成功之后再 build 目錄下生成 fd.img 和 disk.i

19、mg 文件。3. 配置啟動 Bochs(1)創(chuàng)建 bochs 配置文件shell# gedit bochsrc(2)在編輯器輸入一下配置內(nèi)容romimage:file=$BXSHARE/BIOS-bochs-latestmegs: 8boot: afloppya: 1_44=fd.img, status=insertedata0-master:type=disk, mode=flat, path=diskc.img, cylinders=0log: ./bochs.out桂林電子科技大學綜合設計說明書用紙 第 10 頁 (3)保存,直接退出 gedit4.5 運行結(jié)果(1)啟動 bochssh

20、ell# bochs f bochsrc(2)選擇 begin simulation(3)結(jié)果:圖 4.3 項目 1 運行結(jié)果5 項目 2 的設計實現(xiàn)5.1 項目設計目的擴充 GeekOS 操作系統(tǒng)內(nèi)核,使得系統(tǒng)能夠支持用戶級進程的動態(tài)創(chuàng)建和執(zhí)行。5.2 項目設計目的1.“src/GeekOS/user.c”文件中的函數(shù) Spawn() ,其功能是生成一個新的用戶級進程;2.“src/GeekOS/user.c”文件中的函數(shù) Switch_To_User_Context() ,調(diào)度程序在執(zhí)行一個新的進程前調(diào)用該函數(shù)以切換用戶地址空間;3.“src/GeekOS/elf.c”文件中的函數(shù) Par

21、se_ELF_Executable() 。該函數(shù)的實現(xiàn)要求和項目 1 相同。4.“src/GeekOS/userseg.c”文件中主要是實現(xiàn)一些為實現(xiàn)對“src/GeekOS/user.c”中高層操作支持的函數(shù)。 Destroy_User_Context()函數(shù)的功能是釋放用戶態(tài)進程占用的內(nèi)存資源。 Load_User_Program()函數(shù)的功能通過加載可執(zhí)行文件鏡像創(chuàng)建新進程的桂林電子科技大學綜合設計說明書用紙 第 11 頁 User_Context 結(jié)構(gòu)。 Copy_From_User()和 Copy_To_User()函數(shù)的功能是在用戶地址空間和內(nèi)核地址空間之間復制數(shù)據(jù),在分段存儲器管

22、理模式下,只要段有效,調(diào)用 memcpy 函數(shù)就可以實現(xiàn)這兩個函數(shù)的功能。 Switch_To_Address_Space()函數(shù)的功能是通過將進程的 LDT 裝入到 LDT 寄存器來激活用戶的地址空間;5.“src/GeekOS/kthread.c”文件中的 Start_User_Thread 函數(shù)和 Setup_User_Thread 函數(shù)。 Setup_User_Thread()函數(shù)的功能是為進程初始化內(nèi)核堆棧,堆棧中是為進程首次進入用戶態(tài)運行時設置處理器狀態(tài)要使用的數(shù)據(jù)。 Start_User_Thread()是一個高層操作,該函數(shù)使用 User_Context 對象開始一個新進程。6

23、.“src/GeekOS/kthread.c”文件中主要是實現(xiàn)用戶程序要求內(nèi)核進行服務的一些系統(tǒng)調(diào)用函數(shù)定義。要求用戶實現(xiàn)的有 Sys_Exit()函數(shù)、Sys_PrintString()函數(shù)、Sys_GetKey() 、Sys_SetAttr() 、Sys_GetCursor() 、Sys_PutCursor() 、Sys_Spawn()函數(shù)、Sys_Wait()函數(shù)和 Sys_GetPID( )函數(shù)。7.在 main.c 文件中改寫生成第一個用戶態(tài)進程的函數(shù)調(diào)用:Spawn_Init_Process(void) 。5.3 項目實現(xiàn)原理1. GeekOS 進程狀態(tài)及轉(zhuǎn)換圖 5.1 GeekO

24、S 進程轉(zhuǎn)換GeekOS 系統(tǒng)最早創(chuàng)建的內(nèi)核進程有 Idle、Reaper 和 Main 三個進程,它們由Init_Scheduler 函數(shù)創(chuàng)建:最先初始化一個核態(tài)進程 mainThread,并將該進程作為當前運行進程,函數(shù)最后還調(diào)用 Start_Kernel_Thread 函數(shù)創(chuàng)建了兩個系統(tǒng)進程 Idle 和桂林電子科技大學綜合設計說明書用紙 第 12 頁 Reaper。 所以,Idle、Reaper 和 Main 三個進程是系統(tǒng)中最早存在的進程。2. GeekOS 的用戶態(tài)進程 在 GeekOS 中為了區(qū)分用戶態(tài)進程和內(nèi)核進程,在 Kernel_Thread 結(jié)構(gòu)體中設置了一個字段 use

25、rContext,指向用戶態(tài)進程上下文。對于內(nèi)核進程來說,這個指針為空,而用戶態(tài)進程都擁有自己的用戶上下文(User_Context) 。因此,在 GeekOS 中要判斷一個進程是內(nèi)核進程還是用戶態(tài)進程,只要通過 userContext 字段是否為空來判斷就可以了。 圖 5.2 用戶進程3.用戶進程空間每個用戶態(tài)進程都擁有屬于自己的內(nèi)存段空間,如:代碼段、數(shù)據(jù)段、堆棧段等,每個段有一個段描述符(segment descriptor) ,并且每個進程有一個段描述符表(Local Descriptor Table) ,用于保存該進程的所有段描述符。操作系統(tǒng)中還設置一個全局描述符表(GDT,Glob

26、al Descriptor Table) ,用于記錄了系統(tǒng)中所有進程的 ldt 描述符。圖 5.3 用戶進程空間4. 用戶態(tài)進程創(chuàng)建 LDT 的步驟(1)調(diào)用函數(shù) Allocate_Segment_Descriptor()新建一個 LDT 描述符;桂林電子科技大學綜合設計說明書用紙 第 13 頁 (2)調(diào)用函數(shù) Selector()新建一個 LDT 選擇子;(3)調(diào)用函數(shù) Init_Code_Segment_Descriptor()新建一個文本段描述符;(4)調(diào)用函數(shù) Init_Data_Segment_Descriptor()新建一個數(shù)據(jù)段;(5)調(diào)用函數(shù) Selector()新建一個數(shù)據(jù)段

27、選擇子;(6)調(diào)用函數(shù) Selector()新建一個文本(可執(zhí)行代碼)段選擇子。圖 5.4 用戶進程創(chuàng)建流程5.4 項目實現(xiàn)過程1.添加代碼(1)修改 src/GeekOS/user.c 文件中的函數(shù) Spawn(),其功能是生成一個用戶級進程。(2)src/GeekOS/user.c 文件中的函數(shù) Switch_To_User_Contex(),調(diào)度程序在執(zhí)行一個新的進程前調(diào)用該函數(shù)以切換用戶地址空間。(3)src/GeekOS/elf.c 文件中的函數(shù) Prase_ELF_Executable()。該函數(shù)的實現(xiàn)要求和項目 1 相同。(4)src/GeekOS/userseg.c 文件主要是

28、實現(xiàn)一些為實現(xiàn)對 src/GeekOS/user.c 中高層操作支持的函數(shù)。 Destroy_User_Context()函數(shù)的功能是釋放用戶態(tài)進程占用的內(nèi)存資源。桂林電子科技大學綜合設計說明書用紙 第 14 頁 Load_User_Program()函數(shù)的功能通過加載可執(zhí)行文件鏡像創(chuàng)建新進程的 User_Context 結(jié)構(gòu)。 Copy_From_User()和 Copy_To_User()函數(shù)的功能是在用戶地址空間和內(nèi)核地址空間之間復制數(shù)據(jù),在分段存儲器管理模式下,只要段有效,調(diào)用 memcpy 函數(shù)就可以實現(xiàn)這兩個函數(shù)的功能。 Switch_To_Address_Space()函數(shù)的功能

29、是通過將進程的 LDT 裝入到 LDT 寄存器來激活用戶的地址空間(5)src/GeekOS/kthread.c 文件中 Start_User_Thread 函數(shù)和 Setup_User_Thread 函數(shù)。 Setup_User_Thread()函數(shù)的功能是為進程初始化內(nèi)核堆棧,堆棧中是為進程首次進入用戶態(tài)運行時設置處理器狀態(tài)要使用的數(shù)據(jù)。 Start_User_Thread()是一個高層操作,該函數(shù)使用 User_Context 對象開始一個新進程。(6)src/GeekOS/kthread.c 相關(guān)函數(shù)的修改。(7)src/GeekOS/syscall.c”文件中主要是實現(xiàn)用戶程序要求內(nèi)

30、核進行服務的一些系統(tǒng)調(diào)用函數(shù)定義。 要求用戶實現(xiàn)的有 Sys_Exit()函數(shù)、Sys_PrintString()函數(shù)、Sys_GetKey() 、Sys_SetAttr() 、Sys_GetCursor() 、Sys_PutCursor() 、Sys_Spawn()函數(shù)、Sys_Wait()函數(shù)和 Sys_GetPID( )函數(shù)。(8)在 main.c 文件中改寫生成第一個用戶態(tài)進程的函數(shù)調(diào)用:Spawn_Init_Process(void) = user.c =/產(chǎn)生一個進程(用戶態(tài))int Spawn(const char *program, const char *command, s

31、truct Kernel_Thread *pThread) /TODO(Spawn a process by reading an executable from a filesystem); int rc; /標記各函數(shù)的返回值,為 0 則表示成功,否則失敗 char *exeFileData = 0;/保存在內(nèi)存緩沖中的用戶程序可執(zhí)行文件 ulong_t exeFileLength;/可執(zhí)行文件的長度 struct User_Context *userContext = 0;/指向 User_Conetxt 的指針 struct Kernel_Thread *process = 0;/指向

32、 Kernel_Thread *pThread 的指針 struct Exe_Format exeFormat;/調(diào)用 Parse_ELF_Executable 函數(shù)得到的可執(zhí)行文件信息 if (rc = Read_Fully(program, (void*) &exeFileData, &exeFileLength) != 0 ) /調(diào)用 Read_Fully 函數(shù)將名為 program 的可執(zhí)行文件全部讀入內(nèi)存緩沖區(qū) Print(Failed to Read File %s!n, program); goto fail; if(rc = Parse_ELF_Executab

33、le(exeFileData, exeFileLength, &exeFormat) != 0 ) /調(diào)用 Parse_ELF_Executable 函數(shù)分析 ELF 格式文件 Print(Failed to Parse ELF File!n); goto fail; if(rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext) != 桂林電子科技大學綜合設計說明書用紙 第 15 頁 0) /調(diào)用 Load_User_Program 將可執(zhí)行程序的程序段和

34、數(shù)據(jù)段裝入內(nèi)存 Print(Failed to Load User Program!n); goto fail; /在堆分配方式下釋放內(nèi)存并再次初始化 exeFileData Free(exeFileData); exeFileData = 0;/* 開始用戶進程,調(diào)用 Start_User_Thread 函數(shù)創(chuàng)建一個進程并使其進入準備運行隊列*/ process = Start_User_Thread(userContext, false); if (process != 0) /不是核心級進程(即為用戶級進程) KASSERT(process-refCount = 2);/* 返回核心進程

35、的指針 */ *pThread = process; rc = process-pid;/記錄當前進程的 ID else/超出內(nèi)存 project2includegeekoserrno.h rc = ENOMEM; return rc;fail: /如果新進程創(chuàng)建失敗則注銷 User_Context 對象 if (exeFileData != 0) Free(exeFileData);/釋放內(nèi)存 if (userContext != 0) Destroy_User_Context(userContext);/銷毀進程對象 return rc;-/切換至用戶上下文void Switch_To_U

36、ser_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state) /TODO(Switch to a new user address space, if necessary); static struct User_Context* s_currentUserContext; /* last user context used */ /extern int userDebug; struct User_Context* userContext = kthread-userContext;/指向 User_Con

37、etxt 的指針,并初始化為準備切換的進程 KASSERT(!Interrupts_Enabled(); if (userContext = 0) /userContext 為 0 表示此進程為核心態(tài)進程就不用切換地址空間 return; if (userContext != s_currentUserContext) ulong_t esp0; /if (userDebug) Print(A%pn, kthread); Switch_To_Address_Space(userContext);/為用戶態(tài)進程時則切換地址空間 esp0 = (ulong_t) kthread-stackPage

38、) + PAGE_SIZE; /if (userDebug) / Print(S%lxn, esp0);/* 新進程的核心棧. */桂林電子科技大學綜合設計說明書用紙 第 16 頁 Set_Kernel_Stack_Pointer(esp0);/設置內(nèi)核堆棧指針/* New user context is active */ s_currentUserContext = userContext; = elf.c =copy project1 = userseg.c =/需在此文件各函數(shù)前增加一個函數(shù),此函數(shù)的功能是按給定的大小創(chuàng)建一個用戶級進程上下文,具體實現(xiàn)如下:/函數(shù)功能:按給定的大小創(chuàng)建

39、一個用戶級進程上下文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); /為用戶態(tài)進程 if (UserContext != 0) UserContext-memory = Malloc(size); /為核心態(tài)進程 else goto fail;

40、/內(nèi)存為空 if (0 = UserContext-memory) goto fail; memset(UserContext-memory, 0, size); UserContext-size = size; /以下為用戶態(tài)進程創(chuàng)建 LDT(段描述符表) /新建一個 LDT 描述符 UserContext-ldtDescriptor = Allocate_Segment_Descriptor(); if (0 = UserContext-ldtDescriptor) goto fail; /初始化段描述符 Init_LDT_Descriptor(UserContext-ldtDescrip

41、tor, UserContext-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 );桂林電

42、子科技大學綜合設計說明書用紙 第 17 頁 /新建一個數(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 UserC

43、ontext-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);/ KASSERT(userContext-refCount = 0);/* Free the co

44、ntexts LDT descriptor */ Free_Segment_Descriptor(userContext-ldtDescriptor);/* Free the contexts memory */ Disable_Interrupts();/ Free(userContext-memory);/ Free(userContext);/ Enable_Interrupts(); /釋放占用的 LDT Free_Segment_Descriptor(userContext-ldtDescriptor); userContext-ldtDescriptor=0; /釋放內(nèi)存空間 Fr

45、ee(userContext-memory); userContext-memory=0; /釋放 userContext 本身占用的內(nèi)存 Free(userContext); userContext=0;桂林電子科技大學綜合設計說明書用紙 第 18 頁 -int Load_User_Program(char *exeFileData, ulong_t exeFileLength,struct Exe_Format *exeFormat, const char *command, struct User_Context *pUserContext) /TODO(Load a user exec

46、utable into a user memory space using segmentation); int i; ulong_t maxva = 0;/要分配的最大內(nèi)存空間 unsigned numArgs;/進程數(shù)目 ulong_t argBlockSize;/參數(shù)塊的大小 ulong_t size, argBlockAddr;/參數(shù)塊地址 struct User_Context *userContext = 0; /計算用戶態(tài)進程所需的最大內(nèi)存空間 for (i = 0; i numSegments; +i) /elf.h struct Exe_Segment *segment =

47、&exeFormat-segmentListi; ulong_t topva = segment-startAddress + segment-sizeInMemory; /* FIXME: range check */ if (topva maxva) maxva = topva; Get_Argument_Block_Size(command, &numArgs, &argBlockSize);/獲取參數(shù)塊信息 size = Round_Up_To_Page(maxva) + DEFAULT_USER_STACK_SIZE;/用戶進程大小=參數(shù)塊總大小 + 進程堆棧

48、大小(8192) argBlockAddr = size; size += argBlockSize; userContext = Create_User_Context(size);/按相應大小創(chuàng)建一個進程 if (userContext = 0)/如果為核心態(tài)進程 return -1; for (i = 0; i numSegments; +i) struct Exe_Segment *segment = &exeFormat-segmentListi; /根據(jù)段信息將用戶程序中的各段內(nèi)容復制到分配的用戶內(nèi)存空間 memcpy(userContext-memory + segmen

49、t-startAddress, exeFileData + segment-offsetInFile,segment-lengthInFile); /格式化參數(shù)塊 Format_Argument_Block(userContext-memory + argBlockAddr, numArgs, argBlockAddr, command); /初始化數(shù)據(jù)段,堆棧段及代碼段信息 userContext-entryAddr = exeFormat-entryAddr; userContext-argBlockAddr = argBlockAddr; userContext-stackPointer

50、Addr = argBlockAddr; /將初始化完畢的 User_Context 賦給*pUserContext *pUserContext = userContext; return 0;/成功-/將用戶態(tài)的進程復制到內(nèi)核緩沖區(qū)bool Copy_From_User(void* destInKernel, ulong_t srcInUser, ulong_t bufSize)桂林電子科技大學綜合設計說明書用紙 第 19 頁 /TODO(Copy memory from user buffer to kernel buffer); struct User_Context * UserCon

51、text = g_currentThread-userContext; /-: check if memory if validated if (!Validate_User_Memory(UserContext,srcInUser, bufSize) return false; /-:user-kernel memcpy(destInKernel, UserContext-memory + srcInUser, bufSize); return true;-/將內(nèi)核態(tài)的進程復制到用戶態(tài)bool Copy_To_User(ulong_t destInUser, void* srcInKerne

52、l, ulong_t bufSize) /TODO(Copy memory from kernel buffer to user buffer) struct User_Context * UserContext = g_currentThread-userContext; /-: check if memory if validated if (!Validate_User_Memory(UserContext, destInUser, bufSize) return false; /-:kernel-user memcpy(UserContext-memory + destInUser,

53、srcInKernel, bufSize); return true;-/切換到用戶地址空間void Switch_To_Address_Space(struct User_Context *userContext) /TODO(Switch to user address space using segmentation/LDT); ushort_t ldtSelector= userContext-ldtSelector;/* Switch to the LDT of the new user context */ _asm_ _volatile_ (lldt %0:a(ldtSelect

54、or); = kthread.c =添加頭文件 #include -/創(chuàng)建一個用戶進程/*static*/ void Setup_User_Thread(struct Kernel_Thread* kthread, struct User_Context* userContext) /TODO(Create a new thread to execute in user mode); ulong_t eflags = EFLAGS_IF; unsigned csSelector=userContext-csSelector;/CS 選擇子 unsigned dsSelector=userCon

55、text-dsSelector;/DS 選擇子 Attach_User_Context(kthread, userContext); /初始化用戶態(tài)進程堆棧,使之看上去像剛被中斷運行一樣 /分別調(diào)用 Push 函數(shù)將以下數(shù)據(jù)壓入堆棧 Push(kthread, dsSelector); /數(shù)據(jù)選擇子 Push(kthread, userContext-stackPointerAddr); /堆棧指針 Push(kthread, eflags); /Eflags Push(kthread, csSelector); /文本選擇子桂林電子科技大學綜合設計說明書用紙 第 20 頁 Push(kthr

56、ead, userContext-entryAddr); /程序計數(shù)器 Push(kthread, 0); /錯誤代碼(0) Push(kthread, 0); /中斷號(0) /初始化通用寄存單元,將 ESI 用戶傳遞參數(shù)塊地址 Push(kthread, 0); /* eax */ Push(kthread, 0); /* ebx */ Push(kthread, 0); /* edx */ Push(kthread, 0); /* edx */ Push(kthread, userContext-argBlockAddr); /* esi */ Push(kthread, 0); /*

57、edi */ Push(kthread, 0); /* ebp */ /初始化數(shù)據(jù)段寄存單元 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, bool detached) /TODO(Start u

58、ser thread); struct Kernel_Thread* kthread = Create_Thread(PRIORITY_USER, detached); /為用戶態(tài)進程 if (kthread != 0) Setup_User_Thread(kthread, userContext); Make_Runnable_Atomic(kthread); return kthread; = syscall.c =/需在此文件別的函數(shù)前增加一個函數(shù),函數(shù)名為 Copy_User_String,它被函數(shù) Sys_PrintString 調(diào)用,具體實現(xiàn)如下:static int Copy_U

59、ser_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;桂林電子科技大學綜合設計說明書用紙 第 21 頁 goto fail; /從用戶空間中復制數(shù)據(jù) if (!Copy_From_User(str, uaddr, len) rc = EINVALID; Free(

60、str); goto fail; strlen = 0; /成功 *pStr = str;fail: return rc;-static int Sys_Exit(struct Interrupt_State* state) /TODO(Exit system call); Exit(state-ebx);-static int Sys_PrintString(struct Interrupt_State* state) /TODO(PrintString system call); int rc = 0;/返回值 uint_t length = state-ecx;/字符串長度 uchar_t* buf = 0; if (length 0) /* Copy string into kernel. 將字符串復制到內(nèi)核*/ if (rc = Copy_User_String(st

溫馨提示

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

評論

0/150

提交評論