




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
操作系統(tǒng)綜合實(shí)驗(yàn)(20--20年度第學(xué)期)名稱:題目:院系:班級(jí):學(xué)號(hào):學(xué)生姓名:指導(dǎo)教師:成績(jī):日期:年月實(shí)驗(yàn)一:實(shí)驗(yàn)環(huán)境的使用一、實(shí)驗(yàn)?zāi)康模?、熟悉操作系統(tǒng)集成實(shí)驗(yàn)環(huán)境OSLab的基本使用方法。2、練習(xí)編譯、調(diào)試EOS操作系統(tǒng)內(nèi)核以及EOS應(yīng)用程序。二、實(shí)驗(yàn)內(nèi)容:1、啟動(dòng)OSLab2、學(xué)習(xí)OSLab的基本使用方法3、EOS內(nèi)核項(xiàng)目的生成和調(diào)試4、EOS應(yīng)用程序項(xiàng)目的生成和調(diào)試5、退出OSLab6、保存EOS內(nèi)核項(xiàng)目三、實(shí)驗(yàn)過(guò)程:本實(shí)驗(yàn)實(shí)驗(yàn)過(guò)程主要按照eos操作系統(tǒng)實(shí)驗(yàn)教程上所對(duì)應(yīng)的章節(jié)來(lái)進(jìn)行。實(shí)驗(yàn)結(jié)果:(一)啟動(dòng)OSLab:(無(wú))(二)學(xué)習(xí)OSLab的基本使用方法:(1)、創(chuàng)建了第一個(gè)項(xiàng)目:(2)、生成了第一個(gè)項(xiàng)目(3)、添加了func文件后經(jīng)過(guò)一系列的調(diào)試,打印出了相關(guān)內(nèi)容,按shift+F5結(jié)束調(diào)試。(4)、查看變量的值:有3種方法:1、將鼠標(biāo)移動(dòng)到源代碼編輯器中變量n的名稱上,此時(shí)會(huì)彈出一個(gè)窗口顯示出變量n當(dāng)前的值(由于此時(shí)還沒(méi)有給變量n賦值,所以是一個(gè)隨機(jī)值)。2、在源代碼編輯器中變量n的名稱上點(diǎn)擊鼠標(biāo)右鍵,在彈出的快捷菜單中選擇“快速監(jiān)視”,可以使用“快速監(jiān)視”對(duì)話框查看變量n的值。然后,可以點(diǎn)擊“關(guān)閉”按鈕關(guān)閉“快速監(jiān)視”對(duì)話框。3、在源代碼編輯器中變量n的名稱上點(diǎn)擊鼠標(biāo)右鍵,在彈出的快捷菜單中選擇“添加監(jiān)視”,變量n就被添加到了“監(jiān)視”窗口中。使用“監(jiān)視”窗口可以隨時(shí)查看變量的值和類(lèi)型。此時(shí)按F10進(jìn)行一次單步調(diào)試,可以看到“監(jiān)視”窗口中變量n的值會(huì)變?yōu)?(1)、調(diào)用堆棧:使用“調(diào)用堆?!贝翱诳梢栽谡{(diào)試的過(guò)程中查看當(dāng)前堆棧上的函數(shù),還可以幫助理解函數(shù)的調(diào)用層次和調(diào)用過(guò)程。EOS內(nèi)核項(xiàng)目的生成和調(diào)試:(2)、新建EOS內(nèi)核項(xiàng)目(3)、生成項(xiàng)目(4)、調(diào)試項(xiàng)目(5)、查看軟盤(pán)鏡像文件中的內(nèi)容(6)、查看EOSSDK(SoftwareDevelopmentKit)文件夾EOS應(yīng)用程序項(xiàng)目的生成和調(diào)試新建EOS應(yīng)用程序項(xiàng)目生成項(xiàng)目:按F7生成項(xiàng)目調(diào)試項(xiàng)目:按F5進(jìn)行各種調(diào)試查看軟盤(pán)鏡像文件中的內(nèi)容:使用FloppyImageEditor工具打開(kāi)該項(xiàng)目中的Floppy.img文件,查看軟盤(pán)鏡像中的文件。(三)退出(四)保存四、思考與練習(xí):1.在哪些情況下應(yīng)該使用“逐過(guò)程”調(diào)試,在哪些情況下應(yīng)該使用“逐語(yǔ)句”調(diào)試。答:逐語(yǔ)句為每執(zhí)行一行語(yǔ)句,如果碰到函數(shù)調(diào)用它就會(huì)進(jìn)入到函數(shù)里面。而逐過(guò)程碰到函數(shù)時(shí)不進(jìn)入函數(shù),把函數(shù)調(diào)用當(dāng)成一條語(yǔ)句去執(zhí)行。2.生成EOSSDK文件夾的目的和作用。明白文件夾的組織結(jié)構(gòu)和各個(gè)文件的來(lái)源和作用。查看EOS應(yīng)用程序包含了SDK文件夾中的哪些頭文件,是如何包含的?(1)EOSSDK為應(yīng)用程序調(diào)用系統(tǒng)API提供服務(wù),可作為用戶編程中使用的工具包集合。(2)其主要包括INC頭文件LIB文件夾、導(dǎo)入庫(kù)文件和BIN文件夾、動(dòng)態(tài)鏈接庫(kù)、可執(zhí)行程序、二進(jìn)制文件。(3)包含的頭文件有:eos.h負(fù)責(zé)導(dǎo)出API函數(shù),eosdef.h聲明負(fù)責(zé)導(dǎo)出函數(shù)類(lèi)型的定義,error.h負(fù)責(zé)導(dǎo)出錯(cuò)誤碼。(4)EOS應(yīng)用程序在項(xiàng)目的頭文件中只是包含了eos.h文件,在eos.h文件中又包含了eosdef.h和error.h文件。五、實(shí)驗(yàn)總結(jié):通過(guò)實(shí)驗(yàn)1,我主要了解了oslab的基本使用方法和生成項(xiàng)目的方法。并且懂得了如何查看軟盤(pán)文件中的文件實(shí)驗(yàn)二:操作系統(tǒng)的使用一、實(shí)驗(yàn)?zāi)康母櫿{(diào)試EOS在PC機(jī)上從加電復(fù)位到成功啟動(dòng)的全過(guò)程,了解操作系統(tǒng)的啟動(dòng)過(guò)程。查看EOS啟動(dòng)后的狀態(tài)和行為,理解操作系統(tǒng)啟動(dòng)后的工作方式。二、實(shí)驗(yàn)內(nèi)容及其實(shí)驗(yàn)步驟1.準(zhǔn)備實(shí)驗(yàn)(1).啟動(dòng)OSLab。(2).新建一個(gè)EOSKernel項(xiàng)目。(3).在“項(xiàng)目管理器”窗口中打開(kāi)boot文件夾中的boot.asm和loader.asm兩個(gè)匯編文件。boot.asm是軟盤(pán)引導(dǎo)扇區(qū)程序的源文件,loader.asm是loader程序的源文件。簡(jiǎn)單閱讀一下這兩個(gè)文件中的NASM匯編代碼和注釋。(4).按F7生成項(xiàng)目。(5).生成完成后,使用Windows資源管理器打開(kāi)項(xiàng)目文件夾中的Debug文件夾。找到由boot.asm生成的軟盤(pán)引導(dǎo)扇區(qū)程序boot.bin文件,該文件的大小一定為512字節(jié)(與軟盤(pán)引導(dǎo)扇區(qū)的大小一致)。找到由loader.asm生成的loader程序loader.bin文件,記錄下此文件的大小1566字節(jié),在下面的實(shí)驗(yàn)中會(huì)用到。找到由其它源文件生成的操作系統(tǒng)內(nèi)核文件kernel.dll。2.調(diào)試EOS操作系統(tǒng)的啟動(dòng)過(guò)程2.1使用Bochs做為遠(yuǎn)程目標(biāo)機(jī)2.2調(diào)試BIOS程序啟動(dòng)調(diào)試后,Bochs在CPU要執(zhí)行的第一條指令(即BIOS的第一條指令)處中斷。此時(shí),Display窗口沒(méi)有顯示任何內(nèi)容,Console窗口顯示要執(zhí)行的BIOS第一條指令的相關(guān)信息,并等待用戶輸入調(diào)試命令從Console窗口顯示的內(nèi)容中,我們可以獲得關(guān)于BIOS第一條指令的如下信息:行首的[0xfffffff0]表示此條指令所在的物理地址。f000:fff0表示此條指令所在的邏輯地址(段地址:偏移地址)。jmpfarf000:e05b是此條指令的反匯編代碼。行尾的ea5be000f0是此條指令的十六進(jìn)制字節(jié)碼,可以看出此條指令有5個(gè)字節(jié)。接下來(lái)可以按照下面的步驟,查看CPU在沒(méi)有執(zhí)行任何指令之前主要寄存器中的數(shù)據(jù),以及內(nèi)存中的數(shù)據(jù):.在Console窗口中輸入調(diào)試命令sreg后按回車(chē),顯示當(dāng)前CPU中各個(gè)段寄存器的值,其中CS寄存器信息行中的“s=0xf000”表示CS寄存器的值為0xf000。(2).輸入調(diào)試命令r后按回車(chē),顯示當(dāng)前CPU中各個(gè)通用寄存器的值,如圖10-3。其中“rip:0x00000000:0000fff0”表示IP寄存器的值為0xfff0。(3).輸入調(diào)試命令xp/1024b0x0000,查看開(kāi)始的1024個(gè)字節(jié)的物理內(nèi)存。在Console中輸出的這1K物理內(nèi)存的值都為0,說(shuō)明BIOS中斷向量表還沒(méi)有被加載到此處。(4).輸入調(diào)試命令xp/512b0x7c00,查看軟盤(pán)引導(dǎo)扇區(qū)應(yīng)該被加載到的內(nèi)存位置。輸出的內(nèi)存值都為0,說(shuō)明軟盤(pán)引導(dǎo)扇區(qū)還沒(méi)有被加載到此處。2.3調(diào)試軟盤(pán)引導(dǎo)扇區(qū)程序BIOS在執(zhí)行完自檢和初始化工作后,會(huì)將軟盤(pán)引導(dǎo)扇區(qū)加載到物理地址0x7c00-0x7dff位置,并從0x7c00處的指令開(kāi)始執(zhí)行引導(dǎo)程序,所以接下來(lái)從0x7c00處調(diào)試軟盤(pán)引導(dǎo)扇區(qū)程序NASM匯編器在將boot.asm生成為boot.bin的同時(shí),會(huì)生成一個(gè)boot.lst列表文件,幫助開(kāi)發(fā)者調(diào)試boot.asm文件中的匯編代碼。軟盤(pán)引導(dǎo)扇區(qū)程序的主要任務(wù)就是將軟盤(pán)中的loader.bin文件加載到物理內(nèi)存的0x1000處,然后跳轉(zhuǎn)到loader程序的第一條指令(物理地址0x1000處的指令)繼續(xù)執(zhí)行l(wèi)oader程序。2.4調(diào)試加載程序Loader程序的主要任務(wù)是將操作系統(tǒng)內(nèi)核(kernel.dll文件)加載到內(nèi)存中,然后讓CPU進(jìn)入保護(hù)模式并且啟用分頁(yè)機(jī)制,最后進(jìn)入操作系統(tǒng)內(nèi)核開(kāi)始執(zhí)行(跳轉(zhuǎn)到kernel.dll的入口點(diǎn)執(zhí)行)。2.5調(diào)試內(nèi)核調(diào)試內(nèi)核的步驟如下:(1).在OSLab的“項(xiàng)目管理器”窗口中打開(kāi)ke文件夾中的start.c文件,此文件中只定義了一個(gè)函數(shù),就是操作系統(tǒng)內(nèi)核的入口點(diǎn)函數(shù)KiSystemStartup。(2).在KiSystemStartup函數(shù)中的代碼行(第61行)KiInitializePic();添加一個(gè)斷點(diǎn)。(3).現(xiàn)在可以在Console窗口中輸入調(diào)試命令c繼續(xù)調(diào)試,在剛剛添加的斷點(diǎn)處中斷。(4).在start.c源代碼文件中的KiSystemStartup函數(shù)名上點(diǎn)擊鼠標(biāo)右鍵,在彈出的快捷菜單中選擇“添加監(jiān)視”,KiSystemStartup函數(shù)就被添加到了“監(jiān)視”窗口中。在“監(jiān)視”窗口中可以看到此函數(shù)地址為{void(PVOID)}0x800*****<KiSystemStartup>與在虛擬內(nèi)存x80001117處保存的函數(shù)入口地址相同,說(shuō)明的確是由Loader程序進(jìn)入了操作系統(tǒng)內(nèi)核。(5).按F5繼續(xù)執(zhí)行EOS操作系統(tǒng)內(nèi)核,在Display窗口中顯示EOS操作系統(tǒng)已經(jīng)啟動(dòng),并且控制臺(tái)EOS程序已經(jīng)開(kāi)始運(yùn)行了。2.6EOS啟動(dòng)后的狀態(tài)和行為查看EOS的版本號(hào):(1).在控制臺(tái)中輸入命令“ver”后按回車(chē)。(2).輸出EOS版本后的控制臺(tái)如圖。查看EOS啟動(dòng)后的進(jìn)程和線程的信息:1.在控制臺(tái)中輸入命令“pt”后按回車(chē)。2.輸出的進(jìn)程和線程信息如圖所示。查看有應(yīng)用程序運(yùn)行時(shí)進(jìn)程和線程的信息:1.在OSLab中選擇“調(diào)試”菜單中的“停止調(diào)試”,結(jié)束之前的調(diào)試。2.在OSLab“項(xiàng)目管理器”窗口中雙擊Floppy.img文件,使用FloppyImageEditor工具打開(kāi)此軟盤(pán)鏡像文件。3.打開(kāi)配套資源“學(xué)生包”,在其中找到本實(shí)驗(yàn)對(duì)應(yīng)的文件夾??梢栽诒緯?shū)前言部分找到“學(xué)生包”的下載地址。4.將本實(shí)驗(yàn)文件夾中的Hello.exe文件拖動(dòng)到FloppyImageEditor工具窗口的文件列表中釋放,Hello.exe文件即被添加到軟盤(pán)鏡像文件中。Hello.exe一個(gè)EOS應(yīng)用程序,其源代碼可以參見(jiàn)本實(shí)驗(yàn)文件夾中的Hello.c源文件。5.在FloppyImageEditor中選擇“文件”菜單中的“保存”后關(guān)閉FloppyImageEditor。6.按F5啟動(dòng)調(diào)試。7.待EOS啟動(dòng)完畢,在EOS控制臺(tái)中輸入命令“hello”后按回車(chē)。此時(shí)Hello.exe應(yīng)用程序就開(kāi)始執(zhí)行。8.迅速按Ctrl+F2切換到控制臺(tái)2,并輸入命令“pt”后按回車(chē)。輸出的進(jìn)程和線程信息如圖所示。三.思考與練習(xí)1.為什么EOS操作系統(tǒng)從軟盤(pán)啟動(dòng)時(shí)要使用boot.bin和loader.bin兩個(gè)程序?使用一個(gè)可以嗎?它們各自的主要功能是什么?如果將loader.bin的功能移動(dòng)到boot.bin文件中,則boot.bin文件的大小是否仍然能保持小于512字節(jié)?答:在IDE環(huán)境啟動(dòng)執(zhí)行EOS操作系統(tǒng)時(shí),會(huì)將boot.bin,loader.bin,kernal.dll三個(gè)二進(jìn)制寫(xiě)入軟件鏡像文件中,然后讓虛擬機(jī)來(lái)執(zhí)行軟盤(pán)中的EOS操作系統(tǒng),使用其中一個(gè)是不能運(yùn)行的。2.為什么軟盤(pán)引導(dǎo)扇區(qū)程序選擇將loader.bin加載到第一個(gè)可用區(qū)域的0x1000處呢?這樣做有什么好處?這樣做會(huì)對(duì)loader.bin文件的大小有哪些限制。答:用戶只用兩個(gè)可用區(qū)域,加載位置非此即彼。第一個(gè)可用用戶區(qū)是低地址區(qū),且空間大小比較小,適合容納小文件,所以我們選擇將占用空l(shuí)oder.bin加載到第一用戶區(qū)。優(yōu)點(diǎn):低地址開(kāi)始,便于搜索查找小文件占用小空間,節(jié)約資源。限制:loder.bin文件必須小于1c00k。四.實(shí)驗(yàn)總結(jié)通過(guò)本實(shí)驗(yàn)我了解操作系統(tǒng)的啟動(dòng)過(guò)程,和操作系統(tǒng)啟動(dòng)后的工作方式。在實(shí)驗(yàn)中我查看EOS啟動(dòng)后的狀態(tài)和行為,充分理解了操作系統(tǒng)啟動(dòng)后的工作方式實(shí)驗(yàn)三:進(jìn)程的創(chuàng)建一、實(shí)驗(yàn)?zāi)康模?、練習(xí)使用EOSAPI函數(shù)CreateProcess創(chuàng)建一個(gè)進(jìn)程,掌握創(chuàng)建進(jìn)程的方法,理解進(jìn)程和程序的區(qū)別。2、調(diào)試跟蹤C(jī)reateProcess函數(shù)的執(zhí)行過(guò)程,了解進(jìn)程的創(chuàng)建過(guò)程,理解進(jìn)程是資源分配的單位。二、實(shí)驗(yàn)內(nèi)容:1、準(zhǔn)備實(shí)驗(yàn):新建一個(gè)EOSKernel項(xiàng)目,分別使用Debug配置和Release配置生成此項(xiàng)目。新建一個(gè)EOS應(yīng)用程序項(xiàng)目,使用在第EOSKernel生成的SDK文件夾覆蓋EOS應(yīng)用程序項(xiàng)目文件夾中的SDK文件夾。2、練習(xí)使用控制臺(tái)命令創(chuàng)建EOS應(yīng)用程序的進(jìn)程3、練習(xí)通過(guò)編程的方式讓?xiě)?yīng)用程序創(chuàng)建另一個(gè)應(yīng)用程序的進(jìn)程4、調(diào)試CreateProcess函數(shù)5、調(diào)試PsCreateProcess函數(shù)6、練習(xí)通過(guò)編程的方式創(chuàng)建應(yīng)用程序的多個(gè)進(jìn)程三、實(shí)驗(yàn)過(guò)程:1、準(zhǔn)備實(shí)驗(yàn):(無(wú))2、練習(xí)使用控制臺(tái)命令創(chuàng)建EOS應(yīng)用程序的進(jìn)程:使用FloppyImageEditor工具將本實(shí)驗(yàn)文件夾內(nèi)的Hello.exe文件添加到Floppy.img文件中。啟動(dòng)調(diào)試,在EOS的控制臺(tái)中輸入命令“A:\Hello.exe”后回車(chē)。得到結(jié)果:3、練習(xí)通過(guò)編程的方式讓?xiě)?yīng)用程序創(chuàng)建另一個(gè)應(yīng)用程序的進(jìn)程:使用NewProc.c文件中的源代碼替換之前創(chuàng)建的EOS應(yīng)用程序項(xiàng)目中的EOSApp.c文件內(nèi)的源代碼。啟動(dòng)調(diào)試,得到如下結(jié)果:可以看到父進(jìn)程(EOSApp.exe)首先開(kāi)始執(zhí)行并輸出內(nèi)容,父進(jìn)程創(chuàng)建了子進(jìn)程(Hello.exe)后,子進(jìn)程開(kāi)始執(zhí)行并輸出內(nèi)容,待子進(jìn)程結(jié)束后父進(jìn)程再繼續(xù)執(zhí)行。4、調(diào)試CreateProcess函數(shù):按F5啟動(dòng)調(diào)試EOS應(yīng)用程序,在彈出異常對(duì)話框后點(diǎn)“是”,在main函數(shù)中調(diào)用CreateProcess函數(shù)的代碼行添加一個(gè)斷點(diǎn)。5、調(diào)試PsCreateProcess函數(shù):在PsCreateProcess函數(shù)中找到調(diào)用PspCreateProcessEnvironment函數(shù)的代碼行添加一個(gè)斷點(diǎn)。進(jìn)入此中斷,按F11進(jìn)入PspCreateProcessEnvironment函數(shù)。在調(diào)用ObCreateObject函數(shù)的代碼行添加一個(gè)斷點(diǎn),進(jìn)入此中斷,將表達(dá)式*NewProcess添加到“監(jiān)視”窗口中,監(jiān)視其值得變化。接下來(lái)調(diào)試初始化進(jìn)程控制塊中各個(gè)成員變量的過(guò)程:1)首先創(chuàng)建進(jìn)程的地址空間,即4G虛擬地址空間。2)按F5繼續(xù)調(diào)試,到此斷點(diǎn)處中斷。3)按F10執(zhí)行此行代碼后中斷。4)在“監(jiān)視”窗口中查看進(jìn)程控制塊的成員變量Pas的值已經(jīng)不再是0。說(shuō)明已經(jīng)初始化了進(jìn)程的4G虛擬地址空間。5)使用F10一步步調(diào)試PspCreateProcessEnvironment函數(shù)中后面的代碼,在調(diào)試的過(guò)程中根據(jù)執(zhí)行的源代碼,查看“監(jiān)視”窗口中*NewProcess表達(dá)式的值,。6)當(dāng)從PspCreateProcessEnvironment函數(shù)返回到PsCreateProcess函數(shù)后,停止按F10。此時(shí)“監(jiān)視”窗口中已經(jīng)不能再顯示表達(dá)式*NewProcess的值了,在PsCreateProcess函數(shù)中是使用ProcessObject指針指向進(jìn)程控制塊的,所以將表達(dá)式*ProcessObject添加到“監(jiān)視”窗口中就可以繼續(xù)觀察新建進(jìn)程控制塊中的信息。7)接下來(lái)繼續(xù)使用F10一步步調(diào)試PsCreateProcess函數(shù)中的代碼,同樣要注意觀察執(zhí)行后的代碼修改了進(jìn)程控制塊中的哪些成員變量。8)按F5繼續(xù)執(zhí)行,EOS內(nèi)核會(huì)為剛剛初始化完畢的進(jìn)程控制塊新建一個(gè)進(jìn)程。激活虛擬機(jī)窗口查看新建進(jìn)程執(zhí)行的結(jié)果。9)在OSLab中選擇“調(diào)試”菜單中的“停止調(diào)試”結(jié)束此次調(diào)試。10)選擇“調(diào)試”菜單中的“刪除所有斷點(diǎn)”。6、練習(xí)通過(guò)編程的方式創(chuàng)建應(yīng)用程序的多個(gè)進(jìn)程使用OSLab打開(kāi)本實(shí)驗(yàn)文件夾中的參考源代碼文件NewTwoProc.c,仔細(xì)閱讀此文件中的源代碼。使用NewTwoProc.c文件中的源代碼替換EOS應(yīng)用程序項(xiàng)目中EOSApp.c文件內(nèi)的源代碼,生成后啟動(dòng)調(diào)試,查看多個(gè)進(jìn)程并發(fā)執(zhí)行的結(jié)果。多個(gè)進(jìn)程并發(fā)時(shí),EOS操作系統(tǒng)中運(yùn)行的用戶進(jìn)程可以參見(jiàn)圖11-5。驗(yàn)證一個(gè)程序(hello.exe)可以同時(shí)創(chuàng)建多個(gè)進(jìn)程四.思考與練習(xí)部分修改代碼如下圖所示:(“??”部分為相似的4-9進(jìn)程代碼)if(CreateProcess(&&CreateProcess(&&CreateProcess(??&&CreateProcess({WaitForSingleObject(ProcInfoOne.ProcessHandle,INFINITE);WaitForSingleObject(ProcInfoTwo.ProcessHandle,INFINITE);WaitForSingleObject(ProcInfo3.ProcessHandle,INFINITE);??WaitForSingleObject(ProcInfo10.ProcessHandle,INFINITE);GetExitCodeProcess(ProcInfoOne.ProcessHandle,&ulExitCode);??GetExitCodeProcess(ProcInfo3.ProcessHandle,&ulExitCode);printf(??GetExitCodeProcess(ProcInfo10.ProcessHandle,&ulExitCode);printf(CloseHandle(ProcInfoOne.ProcessHandle);??CloseHandle(ProcInfoTwo.ThreadHandle);CloseHandle(ProcInfo3.ProcessHandle);CloseHandle(ProcInfo3.ThreadHandle);??CloseHandle(ProcInfo10.ProcessHandle);CloseHandle(ProcInfo10.ThreadHandle);2.在PsCreateProcess函數(shù)中調(diào)用了PspCreateProcessEnvironment函數(shù)后又先后調(diào)用了PspLoadProcessImage和PspCreateThread函數(shù),學(xué)習(xí)這些函數(shù)的主要功能。能夠交換這些函數(shù)被調(diào)用的順序嗎?答:PspCreateProcessEnvironment創(chuàng)建了進(jìn)程控制塊,地址空間和分配了句柄表,PspLoadProcessImage將進(jìn)程的可執(zhí)行映象加載的到了進(jìn)程的地址空間中,PspCreateThread創(chuàng)建了進(jìn)程的主線程。這三個(gè)函數(shù)知道自己從哪里開(kāi)始執(zhí)行,執(zhí)行哪些指令,因此不能交換它們的順序。實(shí)驗(yàn)總結(jié)經(jīng)過(guò)這次實(shí)驗(yàn)我練習(xí)使用EOSAPI函數(shù)CreateProcess創(chuàng)建了一個(gè)進(jìn)程,掌握了創(chuàng)建進(jìn)程的方法,理解了進(jìn)程和程序的區(qū)別。同時(shí)我調(diào)試跟蹤C(jī)reateProcess函數(shù)的執(zhí)行過(guò)程,了解進(jìn)程的創(chuàng)建過(guò)程,理解了進(jìn)程是資源分配的單位。實(shí)驗(yàn)四:線程的狀態(tài)和轉(zhuǎn)換一、實(shí)驗(yàn)?zāi)康模?、調(diào)試線程在各種狀態(tài)間的轉(zhuǎn)換過(guò)程,熟悉線程的狀態(tài)和轉(zhuǎn)換。2、通過(guò)為線程增加掛起狀態(tài),加深對(duì)線程狀態(tài)的理解。二、實(shí)驗(yàn)內(nèi)容及步驟:1、準(zhǔn)備實(shí)驗(yàn):新建一個(gè)EOSKernel項(xiàng)目。2、調(diào)試線程狀態(tài)的轉(zhuǎn)換過(guò)程:對(duì)第一步的項(xiàng)目啟動(dòng)調(diào)試,待EOS啟動(dòng)完畢,在EOS控制臺(tái)中輸入命令“l(fā)oop”后按回車(chē)。得到結(jié)果:結(jié)束調(diào)試。接下來(lái)按照下面的步驟調(diào)試線程狀態(tài)轉(zhuǎn)換的過(guò)程:(1).在ke/sysproc.c文件的LoopThreadFunction函數(shù)中,開(kāi)始死循環(huán)的代碼行(第787行)添加一個(gè)斷點(diǎn)。(2).按F5啟動(dòng)調(diào)試。(3).待EOS啟動(dòng)完畢,在EOS控制臺(tái)中輸入命令“l(fā)oop”后按回車(chē)。EOS會(huì)在斷點(diǎn)處中斷執(zhí)行,表明loop線程已經(jīng)開(kāi)始死循環(huán)了。此時(shí),EOS中所有的系統(tǒng)線程要么處于就緒狀態(tài)(其優(yōu)先級(jí)一定小于8,例如系統(tǒng)空閑線程),要么就處于阻塞狀態(tài)(例如控制臺(tái)派遣線程或控制臺(tái)線程),所以,只有優(yōu)先級(jí)為8的loop線程能夠在處理器上執(zhí)行。此時(shí)在虛擬機(jī)窗口中會(huì)看到loop線程在不停執(zhí)行,而之前添加的斷點(diǎn)都沒(méi)有被命中,說(shuō)明此時(shí)還沒(méi)有任何線程的狀態(tài)發(fā)生改變。在開(kāi)始觀察線程狀態(tài)轉(zhuǎn)換過(guò)程之前還有必要做一個(gè)說(shuō)明。在后面的練習(xí)中,會(huì)在loop線程執(zhí)行的過(guò)程中按一次空格鍵,這會(huì)導(dǎo)致EOS依次執(zhí)行下面的操作:(1).控制臺(tái)派遣線程被喚醒,由阻塞狀態(tài)進(jìn)入就緒狀態(tài)。(2).loop線程由運(yùn)行狀態(tài)進(jìn)入就緒狀態(tài)。(3).控制臺(tái)派遣線程由就緒狀態(tài)進(jìn)入運(yùn)行狀態(tài)。(4).待控制臺(tái)派遣線程處理完畢由于空格鍵被按下而產(chǎn)生的鍵盤(pán)事件后,派遣線程會(huì)由運(yùn)行狀態(tài)重新進(jìn)入阻塞狀態(tài),開(kāi)始等待下一個(gè)鍵盤(pán)事件到來(lái)。(5).loop線程由就緒狀態(tài)進(jìn)入運(yùn)行狀態(tài),繼續(xù)執(zhí)行死循環(huán)。線程由運(yùn)行狀態(tài)進(jìn)入就緒狀態(tài)通過(guò)以上的調(diào)試,可以將線程由運(yùn)行狀態(tài)進(jìn)入就緒狀態(tài)的步驟總結(jié)如下:(1)線程中斷運(yùn)行,將線程中斷運(yùn)行時(shí)的上下文保存到線程控制塊中。(2)如果處于運(yùn)行狀態(tài)的線程被更高優(yōu)先級(jí)的線程搶先,就需要將該線程插入其優(yōu)先級(jí)對(duì)應(yīng)的就緒隊(duì)列的隊(duì)首。(注意,如果處于運(yùn)行狀態(tài)的線程主動(dòng)讓出處理器,例如時(shí)間片用完,就需要將程插入其優(yōu)先級(jí)對(duì)應(yīng)的就緒隊(duì)列的隊(duì)尾。)(3)將線程的狀態(tài)由Running修改為Ready。至此,loop線程已經(jīng)進(jìn)入就緒狀態(tài)了,接下來(lái)調(diào)試控制臺(tái)派遣線程會(huì)得到處理器進(jìn)入運(yùn)行狀態(tài)的過(guò)程。4.線程由就緒狀態(tài)進(jìn)入運(yùn)行狀態(tài)通過(guò)以上的調(diào)試,可以將線程由就緒狀態(tài)進(jìn)入運(yùn)行狀態(tài)的步驟總結(jié)如下:(1)將線程從其優(yōu)先級(jí)對(duì)應(yīng)的就緒隊(duì)列中移除。(2)將線程的狀態(tài)由Ready修改為Zero。(3)將線程的狀態(tài)由Zero修改為Running。(4)將線程的上下文從線程控制塊(TCB)復(fù)制到處理器的各個(gè)寄存器中,讓線程從上次停止運(yùn)行的位置繼續(xù)運(yùn)行。至此,控制臺(tái)派遣線程已經(jīng)開(kāi)始運(yùn)行了。因?yàn)榇藭r(shí)沒(méi)有比控制臺(tái)派遣線程優(yōu)先級(jí)更高的線程來(lái)?yè)屨继幚砥鳎钥刂婆_(tái)派遣線程可以一直運(yùn)行,直到將此次由于空格鍵被按下而產(chǎn)生的鍵盤(pán)事件處理完畢,然后控制臺(tái)派遣線程會(huì)由運(yùn)行狀態(tài)重新進(jìn)入阻塞狀態(tài),開(kāi)始等待下一個(gè)鍵盤(pán)事件到來(lái)。5.線程由運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài)通過(guò)以上的調(diào)試,可以將線程由運(yùn)行狀態(tài)進(jìn)入阻塞狀態(tài)的步驟總結(jié)如下:(1)將線程插入等待隊(duì)列的隊(duì)尾。(2)將線程的狀態(tài)由Running修改為Waiting。(3)將線程中斷執(zhí)行,并將處理器上下文保存到該線程的線程控制塊中。至此,控制臺(tái)派遣線程已經(jīng)進(jìn)入阻塞狀態(tài)了。因?yàn)榇藭r(shí)loop線程是就緒隊(duì)列中優(yōu)先級(jí)最高的線程,線程調(diào)度功能會(huì)選擇讓loop線程繼續(xù)執(zhí)行。6.為線程增加掛起狀態(tài):刪除之前添加的所有斷點(diǎn)。按F5啟動(dòng)調(diào)試。待EOS啟動(dòng)完畢,在EOS控制臺(tái)中輸入命令“l(fā)oop”后按回車(chē)。此時(shí)可以看到loop線程的執(zhí)行計(jì)數(shù)在不停增長(zhǎng),說(shuō)明loop線程正在執(zhí)行。記錄下loop線程的ID。按Ctrl+F2切換到控制臺(tái)2,輸入命令“suspend31”(如果loop線程的ID是31)后按回車(chē)。命令執(zhí)行成功的結(jié)果如圖12-2所示。按Ctrl+1切換回控制臺(tái)1,可以看到由于loop線程已經(jīng)成功被掛起,其執(zhí)行計(jì)數(shù)已經(jīng)停止增長(zhǎng)了。此時(shí)占用處理器的是EOS中的空閑線程。Resume原語(yǔ)可以將一個(gè)被Suspend原語(yǔ)掛起的線程(處于靜止就緒狀態(tài))恢復(fù)為就緒狀態(tài)。但是PsResumThread函數(shù)中的這部分代碼(第119行),完成這部分代碼。思考與練習(xí)1.思考一下,在本實(shí)驗(yàn)中,當(dāng)loop線程處于運(yùn)行狀態(tài)時(shí),EOS中還有哪些線程,它們分別處于什么狀態(tài)??梢允褂每刂婆_(tái)命令pt查看線程的狀態(tài)。答:有一個(gè)優(yōu)先級(jí)為0的空閑線程處于就緒狀態(tài),8個(gè)優(yōu)先級(jí)為24的控制臺(tái)線程處于阻塞狀態(tài),1個(gè)優(yōu)先級(jí)的24的控制臺(tái)派遣線程處于阻塞狀態(tài)。2.當(dāng)loop線程在控制臺(tái)1中執(zhí)行,并且在控制臺(tái)2中執(zhí)行suspend命令時(shí),為什么控制臺(tái)1中的loop線程處于就緒狀態(tài)而不是運(yùn)行狀態(tài)?答:在控制臺(tái)2中執(zhí)行suspend命令時(shí),優(yōu)先級(jí)為24的控制臺(tái)2線程搶占處理器,即控制臺(tái)2線程處于運(yùn)行狀態(tài),因此此時(shí)loop處于就緒狀態(tài)。3.總結(jié)一下在圖5-3中顯示的轉(zhuǎn)換過(guò)程,哪些需要使用線程控制塊中的上下文,哪些不需要使用,并說(shuō)明原因。答:就緒→運(yùn)行,運(yùn)行→就緒,運(yùn)行→阻塞需要使用TCB因?yàn)檫@些過(guò)程有線程調(diào)進(jìn)或調(diào)出處理機(jī)的過(guò)程,新建→就緒,阻塞→就緒不需要使用TCB上下文,因?yàn)闆](méi)有占用處理機(jī)資源。4.請(qǐng)讀者找出這些轉(zhuǎn)換過(guò)程的原語(yǔ)操作(關(guān)中斷和開(kāi)中斷)是在哪些代碼中完成的。答:IntState=KeEnableInterrupts(FALSE);//關(guān)中斷KeEnableInterrupts(IntState);//開(kāi)中斷四、實(shí)驗(yàn)總結(jié):通過(guò)這次實(shí)驗(yàn),我明白了loop指令的用法以及resume原語(yǔ)的結(jié)構(gòu)。除此之外我還調(diào)試了線程在各種狀態(tài)間的轉(zhuǎn)換過(guò)程,借此熟悉了線程的狀態(tài)和轉(zhuǎn)換。實(shí)驗(yàn)五:進(jìn)程的同步一、實(shí)驗(yàn)?zāi)康模?、使用EOS的信號(hào)量,編程解決生產(chǎn)者—消費(fèi)者問(wèn)題,理解進(jìn)程同步的意義。2、調(diào)試跟蹤EOS信號(hào)量的工作過(guò)程,理解進(jìn)程同步的原理。3、修改EOS的信號(hào)量算法,使之支持等待超時(shí)喚醒功能(有限等待),加深理解進(jìn)程同步的原理。二、實(shí)驗(yàn)內(nèi)容和步驟:1、準(zhǔn)備實(shí)驗(yàn):新建一個(gè)EOSKernel項(xiàng)目。生成EOSKernel項(xiàng)目,從而在該項(xiàng)目文件中生成SDK文件夾。新建一個(gè)EOS應(yīng)用程序項(xiàng)目。使用在第3步生成的SDK文件夾覆蓋EOS應(yīng)用程序項(xiàng)目文件夾中的SDK文件夾。2、使用EOS的信號(hào)量解決生產(chǎn)者-消費(fèi)者問(wèn)題:在本實(shí)驗(yàn)文件夾中,提供了使用EOS的信號(hào)量解決生產(chǎn)者-消費(fèi)者問(wèn)題的參考源代碼文件pc.c,仔細(xì)閱讀此文件中的源代碼和注釋。使用pc.c文件中的源代碼,替換之前創(chuàng)建的EOS應(yīng)用程序項(xiàng)目中EOSApp.c文件內(nèi)的源代碼。按F5啟動(dòng)調(diào)試。立即激活虛擬機(jī)窗口查看生產(chǎn)者-消費(fèi)者同步執(zhí)行的過(guò)程。結(jié)果:3、調(diào)試EOS信號(hào)量的工作過(guò)程:?jiǎn)?dòng)調(diào)試,在main函數(shù)中創(chuàng)建Empty信號(hào)量的代碼行添加一個(gè)斷點(diǎn)。按F5繼續(xù)調(diào)試,到此斷點(diǎn)處中斷。按F11調(diào)試進(jìn)入CreateSemaphore函數(shù)。可以看到此API函數(shù)只是調(diào)用了EOS內(nèi)核中的PsCreateSemaphoreObject函數(shù)來(lái)創(chuàng)建信號(hào)量對(duì)象。按F11調(diào)試進(jìn)入semaphore.c文件中的PsCreateSemaphoreObject函數(shù)。在semaphore.c文件的頂部查找到PsInitializeSemaphore函數(shù)的定義(第19行),在此函數(shù)的第一行(第39行)代碼處添加一個(gè)斷點(diǎn)。按F5繼續(xù)調(diào)試,到斷點(diǎn)處中斷。觀察PsInitializeSemaphore函數(shù)中用來(lái)初始化信號(hào)量結(jié)構(gòu)體成員的值,應(yīng)該和傳入CreateSemaphore函數(shù)的參數(shù)值是一致的。按F10單步調(diào)試PsInitializeSemaphore函數(shù)執(zhí)行的過(guò)程,查看信號(hào)量結(jié)構(gòu)體被初始化的過(guò)程。打開(kāi)“調(diào)用堆?!贝翱?,查看函數(shù)的調(diào)用層次。生產(chǎn)者和消費(fèi)者剛開(kāi)始執(zhí)行時(shí),用來(lái)放產(chǎn)品的緩沖區(qū)都是空的,所以生產(chǎn)者在第一次調(diào)用WaitForSingleObject函數(shù)等待Empty信號(hào)量時(shí),應(yīng)該不需要阻塞就可以立即返回。由于開(kāi)始時(shí)生產(chǎn)者線程生產(chǎn)產(chǎn)品的速度較快,而消費(fèi)者線程消費(fèi)產(chǎn)品的速度較慢,所以當(dāng)緩沖池中所有的緩沖區(qū)都被產(chǎn)品占用時(shí),生產(chǎn)者在生產(chǎn)新的產(chǎn)品時(shí)就會(huì)被阻塞。只有當(dāng)消費(fèi)者線程從緩沖池中消費(fèi)了一個(gè)產(chǎn)品,從而產(chǎn)生一個(gè)空緩沖區(qū)后,生產(chǎn)者線程才會(huì)被喚醒并繼續(xù)生產(chǎn)14號(hào)產(chǎn)品。4、修改EOS的信號(hào)量算法:現(xiàn)在要求同時(shí)修改PsWaitForSemaphore函數(shù)和PsReleaseSemaphore函數(shù)中的代碼,使這兩個(gè)參數(shù)能夠真正起到作用,使信號(hào)量對(duì)象支持等待超時(shí)喚醒功能和批量釋放功能。測(cè)試方法:修改完畢后,可以按照下面的方法進(jìn)行測(cè)試:1.使用修改完畢的EOSKernel項(xiàng)目生成完全版本的SDK文件夾,并覆蓋之前的生產(chǎn)者-消費(fèi)者應(yīng)用程序項(xiàng)目的SDK文件夾。2.按F5調(diào)試執(zhí)行原有的生產(chǎn)者-消費(fèi)者應(yīng)用程序項(xiàng)目,結(jié)果必須仍然與圖13-2一致。如果有錯(cuò)誤,可以調(diào)試內(nèi)核代碼來(lái)查找錯(cuò)誤,然后在內(nèi)核項(xiàng)目中修改,并重復(fù)步驟1。3.將Producer函數(shù)中等待Empty信號(hào)量的代碼行WaitForSingleObject(EmptySemaphoreHandle,INFINITE);替換為while(WAIT_TIMEOUT==WaitForSingleObject(EmptySemaphoreHandle,300)){printf(4.將Consumer函數(shù)中等待Full信號(hào)量的代碼行WaitForSingleObject(FullSemaphoreHandle,INFINITE);替換為while(WAIT_TIMEOUT==WaitForSingleObject(FullSemaphoreHandle,300)){printf(5.啟動(dòng)調(diào)試新的生產(chǎn)者-消費(fèi)者項(xiàng)目,查看在虛擬機(jī)中輸出的結(jié)果,驗(yàn)證信號(hào)量超時(shí)等待功能是否能夠正常執(zhí)行。如果有錯(cuò)誤,可以調(diào)試內(nèi)核代碼來(lái)查找錯(cuò)誤,然后在內(nèi)核項(xiàng)目中修改,并重復(fù)步驟1。6.如果超時(shí)等待功能已經(jīng)能夠正常執(zhí)行,可以考慮將消費(fèi)者線程修改為一次消費(fèi)兩個(gè)產(chǎn)品,來(lái)測(cè)試ReleaseCount參數(shù)是否能夠正常使用。使用實(shí)驗(yàn)文件夾中NewConsumer.c文件中的Consumer函數(shù)替換原有的Consumer函數(shù)。三.思考與練習(xí)1.思考在ps/semaphore.c文件內(nèi)的PsWaitForSemaphore和PsReleaseSemaphore函數(shù)中,為什么要使用原子操作?答:EOS內(nèi)核中維護(hù)了大量?jī)?nèi)核數(shù)據(jù),正是這些數(shù)據(jù)描述了EOS操作系統(tǒng)的狀態(tài)如果有一組相互關(guān)聯(lián)的內(nèi)核數(shù)據(jù)共同描述了這個(gè)操作系統(tǒng)的某個(gè)狀態(tài),那么在修改這樣一組內(nèi)核數(shù)據(jù)時(shí)就必須保證一致性。這就要求修改這部分?jǐn)?shù)據(jù)的代碼在執(zhí)行過(guò)程中不能被打斷,這種操作叫做“原語(yǔ)操作”。2.根據(jù)本實(shí)驗(yàn)3.3.2節(jié)中設(shè)置斷點(diǎn)和調(diào)試的方法,自己設(shè)計(jì)一個(gè)類(lèi)似的調(diào)試方案來(lái)驗(yàn)證消費(fèi)者線程在消費(fèi)24號(hào)產(chǎn)品時(shí)會(huì)被阻塞,直到生產(chǎn)者線程生產(chǎn)了24號(hào)產(chǎn)品后,消費(fèi)者線程才被喚醒并繼續(xù)執(zhí)行的過(guò)程。答:生產(chǎn)到23號(hào)產(chǎn)品后,進(jìn)程阻塞。實(shí)驗(yàn)總結(jié)經(jīng)過(guò)這次實(shí)驗(yàn),我對(duì)生產(chǎn)者-消費(fèi)者問(wèn)題有了進(jìn)一步的了解,通過(guò)實(shí)驗(yàn)平臺(tái),我深入了解了生產(chǎn)者生產(chǎn)和消費(fèi)者消費(fèi)的全過(guò)程,在實(shí)驗(yàn)中我還嘗試了調(diào)試EOS信號(hào)量的工作過(guò)程,發(fā)現(xiàn)生產(chǎn)者會(huì)因?yàn)榫彌_池滿而堵塞實(shí)驗(yàn)六:時(shí)間片輪轉(zhuǎn)調(diào)度一、實(shí)驗(yàn)?zāi)康?.調(diào)試EOS的線程調(diào)度程序,熟悉基于優(yōu)先級(jí)的搶先式調(diào)度。2.為EOS添加時(shí)間片輪轉(zhuǎn)調(diào)度,了解其它常用的調(diào)度算法。二、預(yù)備知識(shí)閱讀本書(shū)第5章中的第5.4節(jié)。重點(diǎn)理解EOS當(dāng)前使用的基于優(yōu)先級(jí)的搶先式調(diào)度,調(diào)度程序執(zhí)行的時(shí)機(jī)和流程,以及實(shí)現(xiàn)時(shí)間片輪轉(zhuǎn)調(diào)度的細(xì)節(jié)。三、實(shí)驗(yàn)內(nèi)容3.1準(zhǔn)備實(shí)驗(yàn)按照下面的步驟準(zhǔn)備實(shí)驗(yàn):1.啟動(dòng)OSLab。2.新建一個(gè)EOSKernel項(xiàng)目。3.2閱讀控制臺(tái)命令“rr”相關(guān)的源代碼閱讀ke/sysproc.c文件中第690行的ConsoleCmdRoundRobin函數(shù),及該函數(shù)用到的第649行的ThreadFunction函數(shù)和第642行的THREAD_PARAMETER結(jié)構(gòu)體,學(xué)習(xí)“rr”命令是何測(cè)試時(shí)間片輪轉(zhuǎn)調(diào)度的。在閱讀的過(guò)程中需要特別注意下面幾點(diǎn):在ConsoleCmdRoundRobin函數(shù)中使用ThreadFunction函數(shù)做為線程函數(shù),新建了20個(gè)優(yōu)先級(jí)為8的線程,做為測(cè)試時(shí)間片輪轉(zhuǎn)調(diào)度用的線程。在新建的線程中,只有正在執(zhí)行的線程才會(huì)在控制臺(tái)的對(duì)應(yīng)行(第0個(gè)線程對(duì)應(yīng)第0行,第1個(gè)線程對(duì)應(yīng)第1行)增加其計(jì)數(shù),這樣就可以很方便的觀察到各個(gè)線程執(zhí)行的情況??刂婆_(tái)對(duì)于新建的線程來(lái)說(shuō)是一種臨界資源,所以,新建的線程在向控制臺(tái)輸出時(shí),必須使用“關(guān)中斷”和“開(kāi)中斷”進(jìn)行互斥(參見(jiàn)ThreadFunction函數(shù)的源代碼)。由于控制臺(tái)線程的優(yōu)先級(jí)是24,高于新建線程的優(yōu)先級(jí)8,所以只有在控制臺(tái)線程進(jìn)入“阻塞”狀態(tài)后,新建的線程才能執(zhí)行。新建的線程會(huì)一直運(yùn)行,原因是在ThreadFunction函數(shù)中使用了死循環(huán),所以只能在ConsoleCmdRoundRobin函數(shù)的最后調(diào)用TerminateThread函數(shù)來(lái)強(qiáng)制結(jié)束這些新建的線程。按照下面的步驟執(zhí)行控制臺(tái)命令“rr”,查看其在沒(méi)有時(shí)間片輪轉(zhuǎn)調(diào)度時(shí)的執(zhí)行效果:1.按F7生成在本實(shí)驗(yàn)3.1中創(chuàng)建的EOSKernel項(xiàng)目。2.按F5啟動(dòng)調(diào)試。3.待EOS啟動(dòng)完畢,在EOS控制臺(tái)中輸入命令“rr”后按回車(chē)。命令開(kāi)始執(zhí)行后,觀察其執(zhí)行效果,會(huì)發(fā)現(xiàn)并沒(méi)有體現(xiàn)“rr”命令相關(guān)源代碼的設(shè)計(jì)意圖。通過(guò)之前對(duì)這些源代碼的學(xué)習(xí),20個(gè)新建的線程應(yīng)該在控制臺(tái)對(duì)應(yīng)的行中輪流地顯示它們的計(jì)數(shù)在增加,而現(xiàn)在只有第0個(gè)新建的線程在第0行顯示其計(jì)數(shù)在增加,說(shuō)明只有第0個(gè)新建的線程在運(yùn)行,其它線程都沒(méi)有運(yùn)行。造成上述現(xiàn)象的原因是:所有20個(gè)新建線程的優(yōu)先級(jí)都是8,而此時(shí)EOS只實(shí)現(xiàn)了基于優(yōu)先級(jí)的搶先式調(diào)度,還沒(méi)有實(shí)現(xiàn)時(shí)間片輪轉(zhuǎn)調(diào)度,所以至始至終都只有第0個(gè)線程在運(yùn)行,而其它具有相同優(yōu)先級(jí)的線程都沒(méi)有機(jī)會(huì)運(yùn)行,只能處于“就緒”狀態(tài).3.3調(diào)試線程調(diào)度程序在為EOS添加時(shí)間片輪轉(zhuǎn)調(diào)度之前,先調(diào)試一下EOS的線程調(diào)度程序PspSelectNextThread函數(shù),學(xué)習(xí)就緒隊(duì)列、就緒位圖以及線程的優(yōu)先級(jí)是如何在線程調(diào)度程序中協(xié)同工作的,從而加深對(duì)EOS已經(jīng)實(shí)現(xiàn)的基于優(yōu)先級(jí)的搶先式調(diào)度的理解。3.3.1調(diào)試當(dāng)前線程不被搶先的情況正像圖中顯示的,新建的第0個(gè)線程會(huì)一直運(yùn)行,而不會(huì)被其它同優(yōu)先級(jí)的新建線程或者低優(yōu)先級(jí)的線程搶先。按照下面的步驟調(diào)試這種情況在PspSelectNextThread函數(shù)中處理的過(guò)程。3.3.2調(diào)試當(dāng)前線程被搶先的情況如果有比第0個(gè)新建的線程優(yōu)先級(jí)更高的線程進(jìn)入就緒狀態(tài),則第0個(gè)新建的線程就會(huì)被搶先3.4為EOS添加時(shí)間片輪轉(zhuǎn)調(diào)度3.4.1要求修改ps/sched.c文件中的PspRoundRobin函數(shù)(第337行),在其中實(shí)現(xiàn)時(shí)間片輪轉(zhuǎn)調(diào)度算法。3.4.2測(cè)試方法1.代碼修改完畢后,按F7生成EOS內(nèi)核項(xiàng)目。2.按F5啟動(dòng)調(diào)試。3.在EOS控制臺(tái)中輸入命令“rr”后按回車(chē)。應(yīng)能看到20個(gè)線程輪流執(zhí)行的效果3.5修改線程時(shí)間片的大小在成功為EOS添加了時(shí)間片輪轉(zhuǎn)調(diào)度后,可以按照下面的步驟修改時(shí)間片的大小:1.在OSLab的“項(xiàng)目管理器”窗口中找到ps/psp.h文件,雙擊打開(kāi)此文件。2.將ps/psp.h第104行定義的TICKS_OF_TIME_SLICE的值修改為1。4.按F7生成EOS內(nèi)核項(xiàng)目。5.按F5啟動(dòng)調(diào)試。3.在EOS控制臺(tái)中輸入命令“rr”后按回車(chē)。觀察執(zhí)行的效果。還可以按照上面的步驟為T(mén)ICKS_OF_TIME_SLICE取一些其它的極端值,例如20或100等,分別觀察“rr”命令執(zhí)行的效果。通過(guò)分析造成執(zhí)行效果不同的原因,理解時(shí)間片的大小對(duì)時(shí)間片輪轉(zhuǎn)調(diào)度造成的影響四,思考與練習(xí)1.結(jié)合線程調(diào)度執(zhí)行的時(shí)機(jī),說(shuō)明在ThreadFunction函數(shù)中,為什么可以使用“關(guān)中斷”和“開(kāi)中斷”方法來(lái)保護(hù)控制臺(tái)這種臨界資源。結(jié)合線程調(diào)度的對(duì)象說(shuō)明這樣做的原因。答:EOS會(huì)設(shè)置CPU停止響應(yīng)外部設(shè)備產(chǎn)生的硬中斷,也就不會(huì)在由硬中斷觸發(fā)線程調(diào)度。開(kāi)中斷和關(guān)中斷使處理機(jī)在這段時(shí)間屏蔽掉了外界所有中斷,使他線程無(wú)法占用資源。使用開(kāi)中斷和關(guān)中斷進(jìn)程同步不會(huì)改變線程狀態(tài),可以保證那些沒(méi)有獲得處理器的資源都在就緒隊(duì)列中。2.為什么不需要將被中斷線程轉(zhuǎn)入“就緒”狀態(tài)?如果此時(shí)將被中斷線程轉(zhuǎn)入了“就緒”狀態(tài)又會(huì)怎么樣?可以結(jié)合PspRoundRobin函數(shù)和PspSelectNextThread函數(shù)的流程進(jìn)行思考,并使用搶先和不搶先兩種情況進(jìn)行說(shuō)明。答:(1)因?yàn)槠渌麅?yōu)先隊(duì)列的線程等待時(shí)間不能過(guò)長(zhǎng)。(2)若將中斷線程轉(zhuǎn)入就緒隊(duì)列,只有當(dāng)此線程執(zhí)行完畢之后,其他隊(duì)列的線程才有機(jī)會(huì)進(jìn)入就緒隊(duì)列,尤其是當(dāng)其他就緒隊(duì)列中的線程關(guān)于人機(jī)交互的時(shí)候,會(huì)嚴(yán)重影響用戶體驗(yàn)。3.EOS內(nèi)核時(shí)間片大小取60ms,在線程比較多時(shí),就可以觀察出線程輪流執(zhí)行的情況,但是在Windows、Linux等操作系統(tǒng)啟動(dòng)后,正常情況下都有上百個(gè)線程在并發(fā)執(zhí)行,為什么覺(jué)察不到它們被輪流執(zhí)行,并且每個(gè)程序都運(yùn)行的很順利呢?答:因?yàn)闀r(shí)間片選取合適,線程輪流運(yùn)行,體現(xiàn)了其虛擬性。實(shí)驗(yàn)七:分頁(yè)存儲(chǔ)器管理一、實(shí)驗(yàn)?zāi)康?.學(xué)習(xí)i386處理器的二級(jí)頁(yè)表硬件機(jī)制,理解分頁(yè)存儲(chǔ)器管理原理。2.查看EOS應(yīng)用程序進(jìn)程和系統(tǒng)進(jìn)程的二級(jí)頁(yè)表映射信息,理解頁(yè)目錄和頁(yè)表的管理方式。編程修改頁(yè)目錄和頁(yè)表的映射關(guān)系,理解分頁(yè)地址變換原理。二、預(yù)備知識(shí)閱讀本書(shū)第6章。了解i386處理器的二級(jí)頁(yè)表硬件機(jī)制,EOS操作系統(tǒng)的分頁(yè)存儲(chǔ)器管理方式,以及進(jìn)程地址空間的內(nèi)存分布。三、實(shí)驗(yàn)內(nèi)容3.1準(zhǔn)備實(shí)驗(yàn)按照下面的步驟準(zhǔn)備本次實(shí)驗(yàn):1.啟動(dòng)OSLab。2.新建一個(gè)EOS應(yīng)用程序項(xiàng)目。3.2查看EOS應(yīng)用程序進(jìn)程的頁(yè)目錄和頁(yè)表使用OSLab打開(kāi)本實(shí)驗(yàn)文件夾中的memory.c和getcr3.asm文件(將文件拖動(dòng)到OSLab窗口中釋放即可打開(kāi))。仔細(xì)閱讀這兩個(gè)文件中的源代碼和注釋?zhuān)琺ain函數(shù)的流程圖可以參見(jiàn)圖。按照下面的步驟查看EOS應(yīng)用程序進(jìn)程的頁(yè)目錄和頁(yè)表:1.使用memory.c文件中的源代碼替換之前創(chuàng)建的EOS應(yīng)用程序項(xiàng)目中EOSApp.c文件中的源代碼。2.右鍵點(diǎn)擊“項(xiàng)目管理器”窗口中的“源文件”文件夾節(jié)點(diǎn),在彈出的快捷菜單中選擇“添加”中的“添加新文件”。3.在彈出的“添加新文件”對(duì)話框中選擇“asm源文件”模板。4.在“名稱”中輸入文件名稱“func”。5.點(diǎn)擊“添加”按鈕添加并自動(dòng)打開(kāi)文件func.asm。6.將getcr3.asm文件中的源代碼復(fù)制到func.asm文件中。7.按F7生成修改后的EOS應(yīng)用程序項(xiàng)目。8.按F5啟動(dòng)調(diào)試。9.應(yīng)用程序執(zhí)行的過(guò)程中,會(huì)將該進(jìn)程的二級(jí)頁(yè)表映射信息輸出到虛擬機(jī)窗口和OSLab“輸出”窗口中,輸出內(nèi)容如圖16-2(a)。10.將“輸出”窗口中的內(nèi)容復(fù)制到一個(gè)文本文件中。3.3查看應(yīng)用程序進(jìn)程和系統(tǒng)進(jìn)程并發(fā)時(shí)的頁(yè)目錄和頁(yè)表需要對(duì)EOS應(yīng)用程序進(jìn)行一些修改:1.結(jié)束之前的調(diào)試。2.取消EOSApp.c第121行語(yǔ)句的注釋?zhuān)ㄔ撔姓Z(yǔ)句會(huì)等待10秒)。3.按F7生成修改后的EOS應(yīng)用程序項(xiàng)目。4.按F5啟動(dòng)調(diào)試。5.在“Console-1”中會(huì)自動(dòng)執(zhí)行EOSApp.exe,創(chuàng)建該應(yīng)用程序進(jìn)程。利用其等待10秒的時(shí)間,按Ctrl+F2切換到“Console-2”。6.在“Console-2”中輸入命令“mm”后按回車(chē),會(huì)將系統(tǒng)進(jìn)程的二級(jí)頁(yè)表映射信息輸出到虛擬機(jī)窗口和OSLab的“輸出”窗口7.將“輸出”窗口中的內(nèi)容復(fù)制到一個(gè)文本文件中。控制臺(tái)命令“mm”對(duì)應(yīng)的源代碼在EOS內(nèi)核項(xiàng)目ke/sysproc.c文件的ConsoleCmdMemoryMap函數(shù)中(第382行)。閱讀這部分源代碼后會(huì)發(fā)現(xiàn),其與EOSApp.c文件中的源代碼基本類(lèi)似四、思考與練習(xí)1.在本實(shí)驗(yàn)3.3中,如果分配了物理頁(yè)后,沒(méi)有回收,會(huì)對(duì)EOS操作系統(tǒng)造成什么樣的影響?目前EOS操作系統(tǒng)內(nèi)核函數(shù)MiAllocateAnyPages能處理所有物理頁(yè)被分配完畢的情況嗎?答:(1)會(huì)造成自由頁(yè)鏈表和零鏈表不斷減少,甚至為空。所有物理頁(yè)都分配完畢的現(xiàn)象。(2)不能。2.嘗試從性能的角度分析內(nèi)核函數(shù)MiAllocateAnyPages和MiAllocateZeroedPages。嘗試從安全性的角度分析分配零頁(yè)的必要性。答:MiAllocateAnyPages分配物理頁(yè)。首先從空閑頁(yè)鏈表中分配,如果分配空閑鏈表不足則再?gòu)牧沩?yè)鏈表分配。MiAllocateZeroedPages首先從零頁(yè)鏈表中分配,如果零頁(yè)不足則從空閑鏈表分配。3.觀察本實(shí)驗(yàn)3.4中使用“vm”命令輸出的系統(tǒng)進(jìn)程的虛擬地址描述符,可以看到在2號(hào)描述符和3號(hào)描述符之間有兩個(gè)虛擬頁(yè)的空隙,嘗試結(jié)合虛擬頁(yè)的分配和釋放說(shuō)明產(chǎn)生這個(gè)空隙的原因。答:產(chǎn)生空隙是由于虛擬頁(yè)被釋放而造成的。在啟動(dòng)時(shí)會(huì)有一個(gè)初始化線程在初始化完畢之后就退出了,線程的堆棧所占用的虛擬頁(yè)也就被釋放了。4.在本實(shí)驗(yàn)3.5中,調(diào)用MmAllocateVirtualMemory函數(shù)分配虛擬頁(yè)時(shí)只使用了MEM_RESERVE標(biāo)志,沒(méi)有使用MEM_COMMIT標(biāo)志,嘗試說(shuō)明這兩個(gè)標(biāo)志的區(qū)別。答:使用MEM_RESERVE標(biāo)志分配虛擬頁(yè)時(shí),沒(méi)有為其映射實(shí)際的物理頁(yè)。使用MEM_COMMIT標(biāo)志分配虛擬頁(yè)時(shí),會(huì)為其映射實(shí)際的物理頁(yè)。五、實(shí)驗(yàn)總結(jié)通過(guò)這次實(shí)驗(yàn)我學(xué)習(xí)到了i386處理器的二級(jí)頁(yè)表硬件機(jī)制,理解分頁(yè)存儲(chǔ)器管理原理。查看EOS應(yīng)用程序進(jìn)程和系統(tǒng)進(jìn)程的二級(jí)頁(yè)表映射信息,理解頁(yè)目錄和頁(yè)表的管理方式。除此之外還編程修改頁(yè)目錄和頁(yè)表的映射關(guān)系,理解了分頁(yè)地址變換原理。實(shí)驗(yàn)八:磁盤(pán)調(diào)度算法一、實(shí)驗(yàn)?zāi)康?.通過(guò)學(xué)習(xí)EOS實(shí)現(xiàn)磁盤(pán)調(diào)度算法的機(jī)制,掌握磁盤(pán)調(diào)度算法執(zhí)行的條件和時(shí)機(jī)。2.觀察EOS實(shí)現(xiàn)的FCFS、SSTF和SCAN磁盤(pán)調(diào)度算法,了解常用的磁盤(pán)調(diào)度算法。3.編寫(xiě)CSCAN和N-Step-SCAN磁盤(pán)調(diào)度算法,加深對(duì)各種掃描算法的理解。二、預(yù)備知識(shí)閱讀本書(shū)第7章的第7.5節(jié),并結(jié)合io/block.c文件中的IopReceiveRequest函數(shù)(第67行)、IopProcessNextRequest函數(shù)(第181行)、IopDiskSchedule函數(shù)(第378行)和IopReadWriteSector函數(shù)(第263行)的源代碼,理解EOS是如何實(shí)現(xiàn)磁盤(pán)調(diào)度算法的。閱讀ke/sysproc.c文件中第580行的ConsoleCmdDiskSchedule函數(shù)及其調(diào)用的其它函數(shù)(包括第536行的NewThreadAccessCylinder函數(shù)和第499行的AccessCylinderThread函數(shù)),學(xué)習(xí)EOS是如何測(cè)試磁盤(pán)調(diào)度算法的,并體會(huì)這種測(cè)試方法的優(yōu)缺點(diǎn)。三、實(shí)驗(yàn)內(nèi)容1準(zhǔn)備實(shí)驗(yàn)驗(yàn)證先來(lái)先服務(wù)(FCFS)磁盤(pán)調(diào)度算法:目前磁頭初始停留在磁道10,其它被阻塞的線程依次訪問(wèn)磁道8、21、9、78、0、41、10、67、12、10。調(diào)試結(jié)果如下:輸出3驗(yàn)證最短尋道時(shí)間優(yōu)先(SSTF)磁盤(pán)調(diào)度算法輸出結(jié)果StartCylinder:10TID:37Cylinder:10Offset:0=TID:40Cylinder:10Offset:0=TID:33Cylinder:9Offset:1-TID:31Cylinder:8Offset:1-TID:39Cylinder:12Offset:4+TID:32Cylinder:21Offset:9+TID:36Cylinder:41Offset:20+TID:38Cylinder:67Offset:26+TID:34Cylinder:78Offset:11+TID:35Cylinder:0Offset:78-即以109812214167780的順序?qū)さ?驗(yàn)證SSTF算法造成的線程“饑餓”現(xiàn)象修改函數(shù)中的源代碼,使磁頭初始停留在磁道10,而讓其它線程依次訪問(wèn)磁道78、21、9、8、11、41、10、67、12、10。輸出結(jié)果:StartCylinder:10TID:37Cylinder:10Offset:0=TID:40Cylinder:10Offset:0=TID:33Cylinder:9Offset:1-TID:34Cylinder:8Offset:1-TID:35Cylinder:11Offset:3+TID:39Cylinder:12Offset:1+TID:32Cylinder:21Offset:9+TID:36Cylinder:41Offset:20+TID:38Cylinder:67Offset:26+TID:31Cylinder:78Offset:11+即以1098111221416778的順序?qū)さ揽梢园l(fā)現(xiàn),雖然訪問(wèn)78號(hào)磁道的線程的請(qǐng)求第一個(gè)被放入請(qǐng)求隊(duì)列,但卻被推遲到最后才被處理,出現(xiàn)了“饑餓”現(xiàn)象。如果不斷有新線程的請(qǐng)求到達(dá)并被優(yōu)先滿足,則訪問(wèn)78號(hào)磁道的線程的“饑餓”情況就會(huì)更加嚴(yán)重。5驗(yàn)證掃描(SCAN)磁盤(pán)調(diào)度算法輸出結(jié)果:StartCylinder:10TID:37Cylinder:10Offset:0=TID:40Cylinder:10Offset:0=TID:39Cylinder:12Offset:2+TID:32Cylinder:21Offset:9+TID:36Cylinder:41Offset:20+TID:38Cylinder:67Offset:26+TID:34Cylinder:78Offset:11+TID:33Cylinder:9Offset:69-TID:31Cylinder:8Offset:1-TID:35Cylinder:0Offset:8-即以101221416778980的順序?qū)さ?改寫(xiě)SCAN算法改寫(xiě)代碼(部分):PREQUESTpNextRequest=NULL,pNextRequest1=NULL,pNextRequest2=NULL;for(pListEntry=RequestListHead.Next;pListEntry!=&RequestListHead;pListEntry=pListEntry->Next){pRequest=CONTAINING_RECORD(pListEntry,REQUEST,ListEntry);Offset=pRequest->Cylinder-CurrentCylinder;if(0==Offset){pNextRequest=pRequest;gotoRETURN;}if(Offset>0){if(Offset<InsideShortestDistance){InsideShortestDistance=Offset;pNextRequest1=pRequest;}}if(Offset<0){if(-Offset<OutsideShortestDistance){OutsideShortestDistance=-Offset;pNextRequest2=pRequest;}}}if(ScanInside){if(pNextRequest1){returnpNextRequest1;}else{ScanInside=!ScanInside;returnpNextRequest2;}}else{if(pNextRequest2){returnpNextRequest2;}else{ScanInside=!ScanInside;returnpNextRequest1;}}RETURN:returnpNextRequest;}得到輸出結(jié)果與上一結(jié)果相同。7編寫(xiě)循環(huán)掃描(CSCAN)磁盤(pán)調(diào)度算法改寫(xiě)代碼(部分):IopDiskSchedule(VOID){for(pListEntry=RequestListHead.Next;pListEntry!=&RequestListHead;pListEntry=pListEntry->Next){pRequest=CONTAINING_RECORD(pListEntry,REQUEST,ListEntry);Offset=pRequest->Cylinder-CurrentCylinder;if(Offset==0){pNextRequest=pRequest;gotoRETURN;}elseif(Offset>0&&Offset<InsideShortestDistance){InsideShortestDistance=Offset;pNextRequestInside=pRequest;}elseif(Offset<0&&-Offset>OutsideLongestDistance){OutsideLongestDistance=-Offset;pNextRequestOutside=pRequest;}}ScanInside=1;if(pNextRequestInside!=NULL){pNextRequest=pNextRequestInside;}else{pNextRequest=pNextRequestOutside;}RETURN:returnpNextRequest;}輸出結(jié)果:StartCylinder:10TID:37Cylinder:10Offset:0=TID:40Cylinder:10Offset:0=TID:39Cylinder:12Offset:2+TID:32Cylinder:21Offset:9+TID:36Cylinder:41Offset:20+TID:38Cylinder:67Offset:26+TID:34Cylinder:78Offset:11+TID:35Cylinder:0Offset:78-TID:31Cylinder:8Off
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 水閣楊梅山施工方案
- 廣告門(mén)頭施工方案
- 石材粘接施工方案
- 火燒板臺(tái)階施工方案
- 橋梁亮化工程施工方案
- 室外管道安裝施工方案
- TSJNX 002-2024 西安市水平衡測(cè)試報(bào)告編制規(guī)范
- 二零二五年度物流信息承運(yùn)合同模板
- 二零二五年度承攬合同中增值稅稅率變動(dòng)應(yīng)對(duì)策略
- 二零二五年度交通事故人傷賠償公益援助協(xié)議
- 2024年度天津市高校大學(xué)《輔導(dǎo)員》招聘試題(含答案)
- 工廠布局和物料路徑(英文版)
- 低壓電器基礎(chǔ)-固態(tài)繼電器(電氣控制課件)
- 高三二輪復(fù)習(xí)備考指導(dǎo)意見(jiàn)
- 港口散裝液體危險(xiǎn)化學(xué)品港口經(jīng)營(yíng)人的裝卸管理人員從業(yè)資格考試
- 2023年四川省公務(wù)員考試行測(cè)真題及答案解析
- 日本商務(wù)禮儀課件
- 公務(wù)用車(chē)申請(qǐng)表
- 中國(guó)民間傳說(shuō):田螺姑娘
- 分層過(guò)程審核(LPA)檢查表
- 淺談鋼琴即興伴奏在教學(xué)中應(yīng)用現(xiàn)狀及提高方法 論文
評(píng)論
0/150
提交評(píng)論