Greekos操作系統(tǒng)實(shí)驗(yàn)_第1頁(yè)
Greekos操作系統(tǒng)實(shí)驗(yàn)_第2頁(yè)
Greekos操作系統(tǒng)實(shí)驗(yàn)_第3頁(yè)
Greekos操作系統(tǒng)實(shí)驗(yàn)_第4頁(yè)
Greekos操作系統(tǒng)實(shí)驗(yàn)_第5頁(yè)
已閱讀5頁(yè),還剩16頁(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)介

第3頁(yè)操作系統(tǒng)實(shí)驗(yàn)報(bào)告目錄TOC\o"1-3"\h\u10181.實(shí)驗(yàn)?zāi)康?1170192.開發(fā)環(huán)境的搭建 2211332.1在虛擬機(jī)上安裝Linux 2207432.2安裝VMwareTools和實(shí)現(xiàn)文件共享 2218192.3BochsPC模擬器的安裝 2262803.項(xiàng)目具體實(shí)現(xiàn) 2167603.1項(xiàng)目0 221003.1.1項(xiàng)目設(shè)計(jì)要求 3248723.1.2項(xiàng)目設(shè)計(jì)原理 3304003.1.3項(xiàng)目設(shè)計(jì)的具體實(shí)現(xiàn) 473713.1.4系統(tǒng)編譯運(yùn)行的原理及結(jié)果 5239693.2項(xiàng)目1 630533.2.1項(xiàng)目設(shè)計(jì)要求 6208853.2.2項(xiàng)目設(shè)計(jì)原理 6261513.2.3項(xiàng)目設(shè)計(jì)的具體實(shí)現(xiàn) 7128633.2.4系統(tǒng)編譯運(yùn)行的原理及結(jié)果 9167043.3項(xiàng)目2 10185083.3.1項(xiàng)目設(shè)計(jì)要求 10115613.3.2項(xiàng)目設(shè)計(jì)原理 1035853.3.3項(xiàng)目設(shè)計(jì)的具體實(shí)現(xiàn) 1112473.3.4系統(tǒng)編譯運(yùn)行的原理及結(jié)果 18156204.遇到的問(wèn)題及解決辦法 19172875.實(shí)驗(yàn)總結(jié) 19實(shí)驗(yàn)?zāi)康牟僮飨到y(tǒng)是管理系統(tǒng)軟件,硬件資源,控制程序運(yùn)行,改善人機(jī)界面及交互,提供各種服務(wù),合理組織計(jì)算機(jī)工作流程和為用戶有效地使用計(jì)算機(jī)提供良好運(yùn)行環(huán)境的系統(tǒng)軟件,它為用戶使用計(jì)算機(jī)提供了一個(gè)方便,靈活,安全,可靠的工作環(huán)境,它也是其他運(yùn)用軟件賴以存在的基礎(chǔ)。操作系統(tǒng)是計(jì)算機(jī)科學(xué)與技術(shù)專業(yè)核心的課程,涉及到很多方面的知識(shí),概念和原理抽象。在課程學(xué)習(xí)過(guò)程中,主要是學(xué)習(xí)理論知識(shí),而操作系統(tǒng)實(shí)驗(yàn)則從理論轉(zhuǎn)向?qū)嵺`,讓我們親自去編寫一個(gè)操作系統(tǒng)內(nèi)核,從而可以更加深入的理解操作系統(tǒng)軟件的實(shí)現(xiàn)過(guò)程,增強(qiáng)了實(shí)踐動(dòng)手能力。本實(shí)驗(yàn)主要要求我們熟悉GeekOs的項(xiàng)目編譯、調(diào)試和運(yùn)行環(huán)境,掌握GeekOs運(yùn)行工作過(guò)程。熟悉ELF文件格式,了解GeekOs系統(tǒng)如何將ELF格式的用戶可執(zhí)行程序裝入到內(nèi)存,建立內(nèi)核線程并運(yùn)行的實(shí)現(xiàn)技術(shù)。擴(kuò)充GeekOs操作系統(tǒng)內(nèi)核,使得系統(tǒng)能過(guò)支持用戶級(jí)進(jìn)程的動(dòng)態(tài)創(chuàng)建和執(zhí)行。開發(fā)環(huán)境的搭建在實(shí)現(xiàn)這個(gè)過(guò)程中。由于Geekos是開源的基于linux系統(tǒng)開發(fā)的操作系統(tǒng),我們需要用到linux下的編譯環(huán)境。所以需要搭建linux環(huán)境。為了實(shí)現(xiàn)與Windows下的文件進(jìn)行共享,需要安裝VMwareTools軟件包。在運(yùn)行的時(shí)候需要bochspc模擬器來(lái)模擬操作系統(tǒng),所以也需要安裝bochspc模擬器。2.1在虛擬機(jī)上安裝Linux本次環(huán)境的搭建是采用在Windows環(huán)境下先安裝一個(gè)PC虛擬機(jī),然后在虛擬機(jī)上安裝Linux操作系統(tǒng)。本次實(shí)驗(yàn)選擇安裝的虛擬機(jī)軟件VMware,安裝過(guò)程則為首先在相應(yīng)的網(wǎng)站下載此安裝軟件,然后其根據(jù)提示安裝。安裝完成后就會(huì)在桌面上顯示一個(gè)虛擬機(jī)圖標(biāo)VMware-workstation。VMware安裝完成后,可以開始建立虛擬機(jī),每新建一個(gè)虛擬機(jī)都會(huì)要求建立一個(gè)配置文件,這個(gè)配置文件相當(dāng)于電腦中的硬件配置表,用戶可以在配置文件中決定虛擬機(jī)的硬盤如何配置,內(nèi)在多大,準(zhǔn)備運(yùn)行哪種操作系統(tǒng),是否有網(wǎng)絡(luò)等。其中中安裝的過(guò)程中要選取實(shí)驗(yàn)需要的相應(yīng)組件進(jìn)行安裝,其中本次實(shí)驗(yàn)必須需要的組件是:AWK、Diff3、Egrep、gcc、GNUbinutils、GNUMake、Perl、NASM。2.2安裝VMwareTools在虛擬機(jī)上安裝VMwareTools,就相當(dāng)于給Linux安裝各種驅(qū)動(dòng)程序。此步的主要目的就是為了以后的工程運(yùn)行時(shí)能夠?qū)崿F(xiàn)與Windows下的文件進(jìn)行共享,因?yàn)閎ochsPC模擬器要在Windows下運(yùn)行,所以這里的文件就只能通過(guò)這一步的共享,從而達(dá)到在Linux下工程運(yùn)行后得到的build下的鏡像文件替代源文件,從而使得bochsPC模擬器能夠得到所需的鏡像文件。2.3安裝BochsPC模擬器BochsPC模擬器:用來(lái)運(yùn)行GeekOS系統(tǒng)。安裝此軟件只需設(shè)定好想安裝到的文件目錄后一直點(diǎn)下一步就可以安裝成功。最后設(shè)置bochsrc.txt文件。根據(jù)實(shí)驗(yàn)的需要,一般只需要修改以下幾項(xiàng):(1)vgaromimage:$BXSHARE/VGABIOS-lgpl-latest(2)romimage:file=$BXSHARE/BIOS-bochs-latest,address=0xf0000(3)floppya:1_44=fdx.img,status=insertedboot:floppy(4)做Project1的時(shí)候,需要添加一個(gè)磁盤鏡像ata0-master:type=disk,mode=flat,path=diskx.img,cylinders=615,heads=6,spt=17配置完bochsrc.txt以后,而且有了從工程生成的操作系統(tǒng)Geekos就可以用bochs軟件模擬了。到bochs的安裝目錄下,輸入bochs命令,選擇6開始模擬。如果你的操作系統(tǒng)編譯成功,就可以得到想要的結(jié)果。項(xiàng)目具體實(shí)現(xiàn)3.1項(xiàng)目0本項(xiàng)目主要目的是要熟悉GeekOS的項(xiàng)目編譯、調(diào)試和運(yùn)行環(huán)境,掌握GeekOS運(yùn)行工作過(guò)程。3.1.1項(xiàng)目設(shè)計(jì)要求(1)搭建GeekOS的編譯和調(diào)試平臺(tái),掌握GeekOS的內(nèi)核進(jìn)程工作原理。(2)熟悉鍵盤操作函數(shù),編程實(shí)現(xiàn)一個(gè)內(nèi)核進(jìn)程。該進(jìn)程的功能是:接收鍵盤輸入的字符并顯示到屏幕上,當(dāng)輸入Ctrl+D時(shí),結(jié)、束進(jìn)程的運(yùn)行。3.1.2項(xiàng)目設(shè)計(jì)原理在這個(gè)項(xiàng)目里面主要了解兩部分的內(nèi)容:內(nèi)核線程和鍵盤處理,相應(yīng)的文件是thread.c和keyboard.c。Geekos系統(tǒng)的默認(rèn)內(nèi)核只支持內(nèi)核態(tài)的線程,在系統(tǒng)初始化的時(shí)候,main函數(shù)分別執(zhí)行了4個(gè)內(nèi)核函數(shù),一個(gè)內(nèi)核函數(shù)負(fù)責(zé)軟驅(qū)中斷,一個(gè)復(fù)雜鍵盤中斷,還有兩個(gè)負(fù)責(zé)進(jìn)程調(diào)度。函數(shù)Start_Kernel_Thread()其可以生成一個(gè)內(nèi)核線程:1.內(nèi)核線程結(jié)構(gòu)的定義如下:structKernel_Thread{unsignedlongesp;volatileunsignedlongnumTicks;intpriority;DEFINE_LINK(Thread_Queue,Kernel_Thread);void*stackPage;structUser_Context*userContext;structKernel_Thread*owner;intrefCount;Booleanalive;structMutexjoinLock;structConditionjoinCond;};esp字段用來(lái)存放一個(gè)線程掛起的堆棧指針;stackPage字段指向內(nèi)核線程的堆棧頁(yè)面numTicks和priority分別被調(diào)度程序用來(lái)實(shí)現(xiàn)基于先占權(quán)和基于優(yōu)先權(quán)的時(shí)間片調(diào)度。DEFINE_LINK宏定義一個(gè)內(nèi)核線程在線程隊(duì)列上時(shí)的前一個(gè)和后一個(gè)字段。userContext字段如果不為空,則指向一個(gè)線程用戶環(huán)境,它是一個(gè)允許線程執(zhí)行用戶模式的代碼和數(shù)據(jù)的組合段。內(nèi)核線程有兩種方式創(chuàng)建。在內(nèi)核里獨(dú)立運(yùn)行的線程可通過(guò)Start_Kernel_Thread()函數(shù)來(lái)創(chuàng)建,該函數(shù)通過(guò)一個(gè)指針指向一個(gè)執(zhí)行線程體的啟動(dòng)函數(shù)。線程所執(zhí)行的用戶模式的程序由Start_User_Thread()函數(shù)創(chuàng)建,并且用一指針指向一個(gè)用戶環(huán)境和用戶環(huán)境內(nèi)存中代碼入口點(diǎn)的地址。調(diào)用Exit()函數(shù)銷毀內(nèi)核線程。入口參數(shù)分別為:函數(shù)地址,函數(shù)參數(shù)(無(wú)參數(shù)就寫0),優(yōu)先級(jí)設(shè)定,線程屬性(false為內(nèi)核線程,true為用戶線程),返回值Mythread的數(shù)據(jù)類型是staticstructKernel_Thread*thread2.Start_Kernel_Thread完成的工作:Create_Thread(priority,detached)//根據(jù)優(yōu)先級(jí)創(chuàng)建一條線程kthread=Alloc_Page()//為線程分配內(nèi)存空間stackPage=Alloc_Page()Init_Thread(kthread,stackPage,priority,detached)Add_To_Back_Of_All_Thread_List(&s_allThreadList,kthread)Setup_Kernel_Thread(kthread,startFunc,arg)//配置內(nèi)核線程的初始化Make_Runnable_Atomic(kthread);//設(shè)置線程運(yùn)行的原子性操作Disable_Interrupts();//禁止中斷Make_Runnable(kthread);//線程運(yùn)行Enable_Interrupts();//使能中斷3.Geekos處理鍵盤代碼在keyboard.c里面提供了一個(gè)功用函數(shù)KeycodeWait_For_Key(void),循環(huán)等待一個(gè)鍵盤事件,然后返回一個(gè)16位的數(shù)據(jù)Keycode型的,在keyboard.h里定義了所有的鍵盤代碼。Read_Key(Keycode*keycode)函數(shù)可以處理隊(duì)列鍵盤按鍵,可以保存到隊(duì)列中并輸出。關(guān)于Keycode的定義是:低8位用來(lái)表示鍵盤值,通過(guò)s_scanTableNoShift和s_scanTableWithShift這兩個(gè)數(shù)組來(lái)轉(zhuǎn)換相應(yīng)的鍵盤碼為所表示字符的ASCII碼,高六位分別是:KEY_SPECIAL_FLAG(特殊鍵,比如F1,F2)用返回的值key&0x0100就可以判斷是否按下特殊健,1為有效,說(shuō)明是特殊健,0則不是,以下的幾種情況類似KEY_KEYPAD_FLAG(小鍵盤鍵)0x0200KEY_SHIFT_FLAG(左,右SHIFT)0x1000KEY_ALT_FLAG(左,右ALT)0x2000KEY_CTRL_FLAG(左,右CTRL)0x4000KEY_RELEASE_FLAG(鍵彈起來(lái)標(biāo)志位)0x80003.1.3項(xiàng)目設(shè)計(jì)的具體實(shí)現(xiàn)projcet0項(xiàng)目主要是對(duì)main.c文件中的鍵盤相應(yīng)的實(shí)現(xiàn)。我們創(chuàng)建函數(shù)keyboard()。下面是具體的代碼。voidkeyboard(ulong_targ){Keycodekey;Print("PleaseEnterthecharacters.press'Ctrl+d'toexit\n\n");while(true){Set_Current_Attr(ATTRIB(BLACK,RED|BRIGHT));key=Wait_For_Key();if(key==(KEY_CTRL_FLAG+'d')){Print("\n\nKeyEnd\n");break;}if(!(key&KEY_RELEASE_FLAG)&&!(key&KEY_SPECIAL_FLAG)){Print("%c",key);}}}voidMain(structBoot_Info*bootInfo){Init_BSS();Init_Screen();Init_Mem(bootInfo);Init_CRC32();Init_TSS();Init_Interrupts();Init_Scheduler();Init_Traps();Init_Timer();Init_Keyboard();Set_Current_Attr(ATTRIB(BLACK,GREEN|BRIGHT));Print("\n\nWelcometosutingting'sGeekOS!\n\n");Start_Kernel_Thread(keyboard,0,5,1);Set_Current_Attr(ATTRIB(BLACK,GRAY));TODO("Startakernelthreadtoechopressedkeysandprintcounts");Exit(0);}3.1.4系統(tǒng)編譯運(yùn)行的原理及結(jié)果I.編譯源代碼在linux的終端中:(1)輸入:cd+空格+路徑(project0文件下的build文件所在的路徑)(2)終端進(jìn)入build目錄$makedepend$make 如果沒(méi)有問(wèn)題就會(huì)自動(dòng)生成一個(gè)鏡像文件fd.img。II修改bochsrc.txt配置文件其具體的文件bochsrc.txt內(nèi)容如下:#配置模擬器的BIOS和顯示系統(tǒng)的BIOS文件vgaromimage:$BXSHARE/VGABIOS-lgpl-latestromimage:file=$BXSHARE/BIOS-bochs-latest,address=0xf0000#配置模擬器內(nèi)存大小megs:8#配置模擬器從軟盤引導(dǎo)系統(tǒng)boot:a#這是對(duì)模擬器硬盤的描述,其中disk.img是硬盤的映像文件,將其注釋掉,因?yàn)轫?xiàng)目0#不需要硬盤。#軟盤A的描述,其中fd.img為軟盤映像文件floppya:1_44=fd.img,status=inserted#floppya:1_44=fd_aug.img,status=inserted#這是配置模擬器的系統(tǒng)文件keyboard_serial_delay:200floppy_command_delay:500vga_update_interval:300000ips:1000000mouse:enabled=0private_colormap:enabled=0i440fxsupport:enabled=0#配置模擬器的日志文件log:./bochs.outIII.運(yùn)行bochs終端運(yùn)行bochs選擇6即的運(yùn)行結(jié)果如下圖1所示:圖1project0的運(yùn)行結(jié)果3.2項(xiàng)目1本項(xiàng)目主要是為了讓學(xué)生熟悉ELF文件格式,了解Geekos系統(tǒng)如何將ELF

格式的用戶可執(zhí)行程式裝入到內(nèi)存,建立內(nèi)核進(jìn)程并運(yùn)行的實(shí)現(xiàn)技術(shù)。3.2.1項(xiàng)目設(shè)計(jì)要求分析ELF格式的可執(zhí)行文件(包括分析得出ELF文件頭、程序頭,獲取可執(zhí)行文件的長(zhǎng)度,代碼段、數(shù)據(jù)段等信息),并填充Exe_Format數(shù)據(jù)結(jié)構(gòu)中的域值。(1)修改/geekos/elf.c文件:在函數(shù)Parse_ELF_Executable()中添加代碼,分析ELF格式的可執(zhí)行文件(包括分析得出ELF文件頭、程序頭,獲取可執(zhí)行文件長(zhǎng)度,代碼段、數(shù)據(jù)段等信息),并填充Exe_Format數(shù)據(jù)結(jié)構(gòu)中的域值。(2)在Linux環(huán)境下編譯系統(tǒng)得到GeekOS鏡像文件。(3)編寫一個(gè)相應(yīng)的bochs配置文件。(4)在bochs中運(yùn)行GeekOS系統(tǒng)顯示結(jié)果。3.2.2項(xiàng)目設(shè)計(jì)原理項(xiàng)目的主要內(nèi)容是在文件elf.c中函數(shù)Parse_ELF_Executable()添加代碼,實(shí)現(xiàn)對(duì)ELF文件的解釋,裝入到內(nèi)存運(yùn)行,得到指定的結(jié)果.主要是分析ELF文件。為以后的工程執(zhí)行應(yīng)用程序做準(zhǔn)備,需要理解的是ELF的一下原理性。需要關(guān)注以下幾個(gè)數(shù)據(jù)結(jié)構(gòu):具體代碼在\project1include\geekos\elf.h中:typedef struct{unsignedcharident[16];unsignedshorttype;unsignedshortmachine;unsignedintversion;unsignedintentry;unsignedintphoff; //programheader偏移量unsignedintsphoff; //sectionheader的偏移unsignedintflags; //指示具體的進(jìn)程unsignedshortehsize; //elf頭部的大小unsignedshortphentsize; //programheader的大小 unsignedshortphnum; //programheader的個(gè)數(shù)unsignedshortshentsize; unsignedshortshnum;unsignedshortshstrndx;}elfHeader;structExe_Format{structExe_SegmentsegmentList[EXE_MAX_SEGMENTS];//段的定義intnumSegments; //可執(zhí)行文件中段的個(gè)數(shù)ulong_tentryAddr; //代碼入口};structExe_Segment{ulong_toffsetInFile; //段在可執(zhí)行文件中的偏移ulong_tlengthInFile; //段在可執(zhí)行文件中的長(zhǎng)度 ulong_tstartAddress; //段在內(nèi)存中的起始地址ulong_tsizeInMemory; //段在內(nèi)存中的大小intprotFlags; //VM保護(hù)標(biāo)志};typedefstruct{unsignedinttype;unsignedintoffset;unsignedintvaddr;unsignedintpaddr;unsignedintfileSize; unsignedintmemSize;unsignedintflags;unsignedintalignment;}programHeader;offset 表示該成員給出了該段的駐留位置相對(duì)于文件開始處的偏移。fileSize表示該成員給出了文件映像中該段的字節(jié)數(shù);它可能是0。memSize表示該成員給出了內(nèi)存映像中該段的字節(jié)數(shù);它可能是0。vaddr 表示該成員給出了該段在內(nèi)存中的首字節(jié)地址。flags表示該成員給出了和該段相關(guān)的標(biāo)志。這是編程實(shí)現(xiàn)過(guò)程主要部分,對(duì)linux下ELF有一定了解之后,就能順利的完成工程項(xiàng)目設(shè)計(jì)的具體實(shí)現(xiàn)下面是project1\src\geekos下的elf.c中的代碼。#include<geekos/errno.h>#include<geekos/kassert.h>#include<geekos/ktypes.h>#include<geekos/screen.h>/*fordebugPrint()statements*/#include<geekos/pfat.h>#include<geekos/malloc.h>#include<geekos/string.h>#include<geekos/elf.h>intParse_ELF_Executable(char*exeFileData,ulong_texeFileLength,structExe_Format*exeFormat){inti;elfHeader*head=(elfHeader*)exeFileData;programHeader*proHeader=(programHeader*)(exeFileData+head->phoff);Set_Current_Attr(ATTRIB(BLACK,BLUE|BRIGHT));Print("ident=%s,",head->ident);Print("type=%d,",head->type);Print("machine=%d,",head->machine);Print("version=%d\n",head->version);Print("entry=%d,",head->entry);Print("phoff=%d,",head->phoff);Print("sphoff=%d,",head->sphoff);Print("flags=%d\n",head->flags);Print("ehsize=%d,",head->ehsize);Print("phentsize=%d,",head->phentsize);Print("phnum=%d,",head->phnum);Print("shentsize=%d\n",head->shentsize);Print("shnum=%d,",head->shnum);Print("shstrndx=%d\n",head->shstrndx);Set_Current_Attr(ATTRIB(BLACK,RED|BRIGHT));Print("type=%d,",proHeader->type);Print("offset=%d,",proHeader->offset);Print("vaddr=%d,",proHeader->vaddr);Print("paddr=%d\n",proHeader->paddr);Print("fileSize=%d,",proHeader->fileSize);Print("memSize=%d,",proHeader->memSize);Print("flags=%d,",proHeader->flags);Print("alignment=%d\n",proHeader->alignment);Set_Current_Attr(ATTRIB(BLACK,GREEN|BRIGHT));for(i=0;i<head->phnum;i++)//programheadertablenumber{exeFormat->segmentList[i].offsetInFile=proHeader->offset;exeFormat->segmentList[i].lengthInFile=proHeader->fileSize;exeFormat->segmentList[i].startAddress=proHeader->vaddr;exeFormat->segmentList[i].sizeInMemory=proHeader->memSize;exeFormat->segmentList[i].protFlags=proHeader->flags;proHeader++;}exeFormat->numSegments=head->phnum;exeFormat->entryAddr=head->entry;return0;}3.2.4系統(tǒng)編譯運(yùn)行的原理及結(jié)果I.編譯源代碼在linux的終端中:(1)輸入:cd+空格+路徑(project1文件下的build文件所在的路徑)(2)終端進(jìn)入build目錄$makedepend$make 如果沒(méi)有問(wèn)題就會(huì)自動(dòng)生成兩個(gè)鏡像文件fd.img和diskc.img。II修改.bochsrc.txt配置文件其具體的文件bochsrc.txt內(nèi)容如下:vgaromimage:$BXSHARE/VGABIOS-lgpl-latestromimage:file=$BXSHARE/BIOS-bochs-latest,address=0xf0000megs:8boot:a#diskc:file=diskc.img,cyl=40,heads=8,spt=64#這是對(duì)模擬器硬盤的描述,其中disk.img是硬盤的映像文件。ata0:enabled=1,ioaddr1=0x1f0,ioaddr2=0x3f0,irq=14ata0-master:type=disk,mode=flat,path=diskc.img,cylinders=40,heads=8,spt=64floppya:1_44=fd.img,status=inserted#floppya:1_44=fd_aug.img,status=insertedkeyboard_serial_delay:200floppy_command_delay:500vga_update_interval:300000ips:1000000mouse:enabled=0private_colormap:enabled=0i440fxsupport:enabled=0log:./bochs.outIII.運(yùn)行bochs終端運(yùn)行bochs選擇6即的運(yùn)行結(jié)果如下圖2所示:圖2project1的運(yùn)行結(jié)果3.3項(xiàng)目2本項(xiàng)目主要的任務(wù)是擴(kuò)展Geekos操作系統(tǒng)內(nèi)核,使得系統(tǒng)能夠支持用戶級(jí)進(jìn)程的動(dòng)態(tài)創(chuàng)建和執(zhí)行。3.3.1項(xiàng)目設(shè)計(jì)要求(1)修改user.c中的函數(shù)Spawn(),其功能是生成一個(gè)新的用戶級(jí)進(jìn)程。(2)修改user.c中函數(shù)Switch_To_UserContext(),調(diào)度程序在執(zhí)行一個(gè)新的進(jìn)程前調(diào)用該函數(shù)以切換用戶地址空間。(3)修改文件elf.c文件中的函數(shù)Parse_ELF_Executable()。這個(gè)在項(xiàng)目一已經(jīng)實(shí)現(xiàn)。(4)修改userseg.c文件中的Destroy_User_Context()、Load_User_Program()、Copy_From_User()、Copy_To_User()和Switch_To_Address_Space()。(5)修改kthread.c文件中的Start_User_Thread()和Setup_User_Thread()函數(shù)(6)實(shí)現(xiàn)kthread.c中的一些系統(tǒng)調(diào)用函數(shù)定義。要求用戶實(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文件中改寫生成第一個(gè)用戶態(tài)進(jìn)程的函數(shù)調(diào)用:Spawn_Init_Process(void)。3.3.2項(xiàng)目設(shè)計(jì)原理項(xiàng)目2需要實(shí)現(xiàn)用戶進(jìn)程,其實(shí)用戶進(jìn)程就是基于內(nèi)核進(jìn)程的一個(gè)改進(jìn)。內(nèi)核進(jìn)程控制塊結(jié)構(gòu)Kernel_Thread中有一個(gè)字段User_Context,而在初始化內(nèi)核進(jìn)程的函數(shù)時(shí)系統(tǒng)將其初始化為零;User_Context字段其實(shí)就是上下文數(shù)據(jù)結(jié)構(gòu),定義如下:StructUser_Context{#defineNUM_USER_LDT_ENTRIES3StructSegment_Descriptorldt[NUM_USRE_LDT_ENTRIES];Structsegment_Descriptor*ldtDsecriptor;Char*memory;Ulong_tsize;Ushort_tldtSelector;Ushort_tcsSelector;Ushort_tdsSelector;Pde_t*pageDir;Ulong_tentryAddr;Ulong_targBlockAddr;Ulong_tstackPointerAddr;IntrefCount;#if0Int*semaphores#endif};StructSegmentDescriptorldt[NUM_USER_LDT_ENTRIES]:是SegmentDescriptor數(shù)組,這里只有兩個(gè)元素,一個(gè)Segment用于用戶進(jìn)程的數(shù)據(jù),一個(gè)Segment用于用戶進(jìn)程的代碼。ldtDescriptor是LDT的描述SegmentDescriptor,memory是用戶內(nèi)存空間的其實(shí)地址。Size是用戶空間的大小。entryAddr是用戶代碼的其實(shí)地址,進(jìn)程就是從這個(gè)地址開始運(yùn)行的。3.3.3項(xiàng)目設(shè)計(jì)的具體實(shí)現(xiàn)主要修改以下文件中的函數(shù):User.c中intSpawn(constchar*program,constchar*command,structKernel_Thread**pThread){

intrc;

char*exeFileData=0;

ulong_texeFileLength;

structUser_Context*userContext=0;

structKernel_Thread*process=0;

structExe_FormatexeFormat;

if((rc=Read_Fully(program,(void**)&exeFileData,&exeFileLength))!=0||

(rc=Parse_ELF_Executable(exeFileData,exeFileLength,&exeFormat))!=0||

(rc=Load_User_Program(exeFileData,exeFileLength,&exeFormat,command,&userContext))!=0)

gotofail;

Free(exeFileData);

exeFileData=0;

/*開始用戶進(jìn)程*/

process=Start_User_Thread(userContext,false);

if(process!=0){

KASSERT(process->refCount==2);

/*返回核心進(jìn)程的指針*/

*pThread=process;

}else

rc=ENOMEM;

returnrc;fail:

if(exeFileData!=0)

Free(exeFileData);

if(userContext!=0)

Destroy_User_Context(userContext);

returnrc;}voidSwitch_To_User_Context(structKernel_Thread*kthread,structInterrupt_State*state){

staticstructUser_Context*s_currentUserContext;

/*lastusercontextused*/

externintuserDebug;

structUser_Context*userContext=kthread->userContext;

KASSERT(!Interrupts_Enabled());

if(userContext==0){

/*核心態(tài)進(jìn)程,無(wú)需改變地址空間.*/

return;

}

if(userContext!=s_currentUserContext){

ulong_tesp0;

if(userDebug)Print("A[%p]\n",kthread);

Switch_To_Address_Space(userContext);

esp0=((ulong_t)kthread->stackPage)+PAGE_SIZE;

if(userDebug)Print("S[%lx]\n",esp0);

/*新進(jìn)程的核心棧.*/

Set_Kernel_Stack_Pointer(esp0);

/*Newusercontextisactive*/

s_currentUserContext=userContext;

}}Elf.c中intParse_ELF_Executable(char*exeFileData,ulong_texeFileLength,

structExe_Format*exeFormat){

inti; elfHeader*head=(elfHeader*)exeFileData; programHeader*proHeader=(programHeader*)(exeFileData+head->phoff); KASSERT(exeFileData!=NULL); KASSERT(exeFileLength>head->ehsize+head->phentsize*head->phnum); KASSERT(head->entry%4==0); exeFormat->numSegments=head->phnum; exeFormat->entryAddr=head->entry; for(i=0;i<head->phnum;i++) { exeFormat->segmentList[i].offsetInFile=proHeader->offset; exeFormat->segmentList[i].lengthInFile=proHeader->fileSize; exeFormat->segmentList[i].startAddress=proHeader->vaddr; exeFormat->segmentList[i].sizeInMemory=proHeader->memSize; exeFormat->segmentList[i].protFlags=proHeader->flags; proHeader++; } return0;}Userseg.c中voidDestroy_User_Context(structUser_Context*userContext){

Free_Segment_Descriptor(userContext->ldtDescriptor); userContext->ldtDescriptor=0; //釋放內(nèi)存空間 Free(userContext->memory); userContext->memory=0; //釋放userContext本身占用的內(nèi)存 Free(userContext); userContext=0;}intLoad_User_Program(char*exeFileData,ulong_texeFileLength,

structExe_Format*exeFormat,constchar*command,

structUser_Context**pUserContext){

inti; ulong_tmaxva=0;//要分配的最大內(nèi)存空間 unsignednumArgs;//進(jìn)程數(shù)目 ulong_targBlockSize;//參數(shù)塊的大小 ulong_tsize,argBlockAddr;//參數(shù)塊地址 structUser_Context*userContext=0; //計(jì)算用戶態(tài)進(jìn)程所需的最大內(nèi)存空間 for(i=0;i<exeFormat->numSegments;++i) { //elf.h structExe_Segment*segment=&exeFormat->segmentList[i]; ulong_ttopva=segment->startAddress+segment->sizeInMemory;/*FIXME:rangecheck*/ if(topva>maxva) { maxva=topva; } } Get_Argument_Block_Size(command,&numArgs,&argBlockSize);//獲取參數(shù)塊信息 size=Round_Up_To_Page(maxva)+DEFAULT_USER_STACK_SIZE;//用戶進(jìn)程大小=參數(shù)塊總大小+進(jìn)程堆棧大小(8192) 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<exeFormat->numSegments;++i) { structExe_Segment*segment=&exeFormat->segmentList[i]; //根據(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->entryAddr=exeFormat->entryAddr; userContext->argBlockAddr=argBlockAddr; userContext->stackPointerAddr=argBlockAddr; //將初始化完畢的User_Context賦給*pUserContext *pUserContext=userContext; return0;//成功}boolCopy_From_User(void*destInKernel,ulong_tsrcInUser,ulong_tbufSize){

structUser_Context*current=g_currentThread->userContext;

if(!Validate_User_Memory(current,srcInUser,bufSize))

returnfalse;

memcpy(destInKernel,User_To_Kernel(current,srcInUser),bufSize);

returntrue;}boolCopy_To_User(ulong_tdestInUser,void*srcInKernel,ulong_tbufSize){

structUser_Context*current=g_currentThread->userContext;

if(!Validate_User_Memory(current,destInUser,bufSize))

returnfalse;

memcpy(User_To_Kernel(current,destInUser),srcInKernel,bufSize);

returntrue;}voidSwitch_To_Address_Space(structUser_Context*userContext){

//TODO("Switchtouseraddressspaceusingsegmentation/LDT"); ushort_tldtSelector=userContext->ldtSelector;/*SwitchtotheLDTofthenewusercontext*/ __asm____volatile__("lldt%0"::"a"(ldtSelector));

}Kthread.c中Start_User_Thread(structUser_Context*userContext,booldetached){

structKernel_Thread*kthread=Create_Thread(PRIORITY_USER,detached);

if(kthread!=0){

Setup_User_Thread(kthread,userContext);

Make_Runnable_Atomic(kthread);

}

returnkthread;}voidSetup_User_Thread(

structKernel_Thread*kthread,structUser_Context*userContext){

//TODO("Createanewthreadtoexecuteinusermode");ulong_teflags=EFLAGS_IF;unsignedcsSelector=userContext->csSelector;//CS選擇子unsigneddsSelector=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ù)選擇子Push(kthread,userContext->stackPointerAddr);//堆棧指針Push(kthread,eflags);//EflagsPush(kthread,csSelector);//文本選擇子Push(kthread,userContext->entryAddr);//程序計(jì)數(shù)器Push(kthread,0);//錯(cuò)誤代碼(0)Push(kthread,0);//中斷號(hào)(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);/*edi*/Push(kthread,0);/*ebp*///初始化數(shù)據(jù)段寄存單元Push(kthread,dsSelector);/*ds*/Push(kthread,dsSelector);/*es*/Push(kthread,dsSelector);/*fs*/Push(kthread,dsSelector);/*gs*/}Syscall.c中staticintSys_Exit(structInterrupt_State*state){

Exit(state->ebx);}staticintSys_PrintString(structInterrupt_State*state){

intrc=0;

uint_tlength=state->ecx;

uchar_t*buf=0;

if(length>0){

/*Copystringintokernel.*/

if((rc=Copy_User_String(state->ebx,length,1023,(char**)&buf))!=0)

gotodone;

/*Writetoconsole.*/

Put_Buf(buf,length);

}done:

if(buf!=0)

Free(buf);

returnrc;}staticintSys_GetKey(structInterrupt_State*state){

returnWait_For_Key();}staticintSys_SetAttr(structInterrupt_State*state){

Set_Current_Attr((uchar_t)state->ebx);

return0;}staticintSys_GetCursor(structInterrupt_State*state){

introw,col;

Get_Cursor(&row,&col);

if(!Copy_To_User(state->ebx,&row,sizeof(int))||

!Copy_To_User(state->ecx,&col,sizeof(int)))

{return-1;}

return0;}staticintSys_PutCursor(structInterrupt_State*state){

returnPut_Cursor(state->ebx,state->ecx)?0:-1;}staticintSys_Spawn(structInterrupt_State*state){

intrc;

char*program=0;

char*command=0;

structKernel_Thread*process;

/*Copyprogramnameandcommandfromuserspace.*/

if((rc=Copy_User_String(state->ebx,state->ecx,VFS_MAX_PATH_LEN,&program))!=0||

(rc=Copy_User_String(state->edx,state->esi,1023,&command))!=0)

gotodone;

Enable_Interrupts();

rc=Spawn(program,command,&process);

if(rc==0){

KASSERT(process!=0);

rc=process->pid;

}

Disable_Interrupts();done:

if(program!=0)

Free(program);

if(command!=0)

Free(command);

returnrc;}staticintSys_Wait(structInterrupt_State*state){

intexitCode;

structKer

溫馨提示

  • 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)論