




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
操作系統(tǒng)課程設(shè)計報告班級:團隊成員:27407目錄 210162一、實驗要求:建立線程系統(tǒng) 3275331.1Task2.1實現(xiàn)文件系統(tǒng)調(diào)用 3230521.1.1題目要求 339641.1.2題目分析與實現(xiàn)方案 3173601.1.3關(guān)鍵點與難點 4252441.1.4實現(xiàn)代碼 4212861.2Task
2.2完成對多道程序的支持 5230521.2.1題目要求 539641.2.2題目分析與實現(xiàn)方案 5173601.2.3關(guān)鍵點與難點 6252441.2.4實現(xiàn)代碼 7212861.3Task
2.3
實現(xiàn)系統(tǒng)調(diào)用 7230521.3.1題目要求 739641.3.2題目分析與實現(xiàn)方案 8173601.3.3關(guān)鍵點與難點 9252441.3.4實現(xiàn)代碼 9317101.4Task2.4實現(xiàn)彩票調(diào)度 10230521.4.1題目要求 1039641.4.2題目分析與實現(xiàn)方案 10173601.4.3關(guān)鍵點與難點 11252441.4.4實現(xiàn)代碼 1110162二、測試結(jié)果 23
一、實驗要求:多道程序設(shè)計1.1Task2.1實現(xiàn)文件系統(tǒng)調(diào)用1.1.1題目要求
實現(xiàn)文件系統(tǒng)調(diào)用(創(chuàng)建,打開,讀,寫,關(guān)閉,unlink),在syscall.h中有詳細的記錄,可以看一下UserProcess.java中的代碼,最好把你自己寫的系統(tǒng)調(diào)用的代碼也放在這里。記住你不是在實現(xiàn)一個文件系統(tǒng),而是在給用戶進程獲取我們給你定義好的文件系統(tǒng)的能力。我們在start.s里為你提供了用戶進程進行系統(tǒng)調(diào)用所必需的匯編代碼。(SYSCALL會為每個系統(tǒng)調(diào)用產(chǎn)生匯編代碼)。其中Unlink為刪除目錄相并減少一個連接數(shù),如果鏈接數(shù)為0并且沒有任何進程打開該文件,該文件內(nèi)容才能被真正刪除,但是若又進程打開了該文件,則文件暫時不刪除直到所有打開該文件的進程都結(jié)束時文件才能被刪除。1.1.2題目分析與實現(xiàn)方案系統(tǒng)共提供了七個系統(tǒng)調(diào)用:halt(停機,已經(jīng)提供),creat(創(chuàng)建并打開磁盤文件),open(打開磁盤文件),read(讀IO,可以是磁盤或屏幕),write(寫IO),close(關(guān)閉IO),unlink(刪除磁盤文件)。要確保如下幾點:1)穩(wěn)定性,不能因為一個進程的非法系統(tǒng)調(diào)用就使操作系統(tǒng)崩潰,而應(yīng)該返回錯誤代碼。2)halt()調(diào)用只能由第一個進程(rootprocess)執(zhí)行。3)系統(tǒng)調(diào)用需要讀寫內(nèi)存時,通過readVirtualMemory和writeVirtualMemory進行。4)文件名以null結(jié)尾,不超過256字符。5)如果系統(tǒng)調(diào)用出錯,應(yīng)返回-1。6)為每個打開的IO文件分配一個“文件描述符”,用整數(shù)表示.每個進程最多可以擁有16個。其中0和1應(yīng)分配給標準輸入和標準輸出(即屏幕),這由SynchConsole類管理。不同進程可以用相同的文件描述符處理不同的文件。7)Nachos已經(jīng)提供了一個簡單的文件系統(tǒng)FileSystem(Machine包中),通過ThreadedKernel.fileSystem訪問。8)系統(tǒng)不需要考慮文件訪問的互斥等問題。方案:1)create系統(tǒng)調(diào)用:1.根據(jù)傳入的fileAddress,從虛擬內(nèi)存中讀出文件名2.判斷文件名是否存在,即fileAddress處是否有文件名3.如果不存在,直接創(chuàng)建。先去找合適的位置,如果已經(jīng)有大于16個,退出,否則創(chuàng)建,創(chuàng)建只需調(diào)用filesystem的open即可(傳入的布爾值create為true)2)open系統(tǒng)調(diào)用:1.根據(jù)傳入的fileAddress,從虛擬內(nèi)存中讀出文件名2.判斷文件名是否存在,即fileAddress處是否有文件名3.先去找合適的位置,如果已經(jīng)有大于16個,退出,否則創(chuàng)建只需調(diào)用filesystem的open即可(傳入的布爾值create為false)4.維護本地描述符表3)read系統(tǒng)調(diào)用Read系統(tǒng)調(diào)用的三個參數(shù)依次為:文件描述符,寫入的內(nèi)存地址,讀取的字節(jié)數(shù)。在Read系統(tǒng)調(diào)用中進行如下操作:1.如果打開文件大于16個或者小于0個,或者打開文件列表為空,直接返回。2.創(chuàng)建數(shù)組temp,把文件內(nèi)容讀入temp,求出讀出數(shù)據(jù)長度3.若讀出數(shù)據(jù)小于0即為出錯,返回。4.把該數(shù)據(jù)寫入虛擬內(nèi)存。5.返回寫入內(nèi)存的字節(jié)數(shù)4)write系統(tǒng)調(diào)用Write系統(tǒng)調(diào)用的三個參數(shù)依次為:文件描述符,讀內(nèi)存的地址,寫入文件的字節(jié)數(shù)。在Write系統(tǒng)調(diào)用中進行如下操作:1.如果打開文件大于16個或者小于0個,或者打開文件列表為空,直接返回。2.創(chuàng)建數(shù)組temp,把虛擬內(nèi)存中的內(nèi)容讀入temp,得到讀出數(shù)據(jù)長度3.若讀出數(shù)據(jù)小于0即為出錯,返回。4.把該數(shù)據(jù)寫入磁盤。5.若寫的數(shù)據(jù)長度小于讀出的數(shù)據(jù)長度,則錯誤,返回錯誤代碼5)close系統(tǒng)調(diào)用Close系統(tǒng)調(diào)用的唯一一個參數(shù)為文件描述符。在Close系統(tǒng)調(diào)用中進行如下操作:1.如果打開文件大于16個或者小于0個,或者打開文件列表為空,直接返回。2.如果不存在,關(guān)閉出錯3.否則關(guān)閉,把openfile數(shù)組中fileDescriptor中的位置置為06)unlink系統(tǒng)調(diào)用:1.根據(jù)傳入的fileAddress,從虛擬內(nèi)存中讀出文件名。2.如果不存在,不必刪除3.如果存在,就刪除,出錯返回錯誤代碼一般地,在Unlink調(diào)用中只需讀取文件名并執(zhí)行fileSystem.remove方法刪除文件即可。但是,一個文件可能被多個進程打開而不能立即刪除,必須等所有打開這個文件的進程都關(guān)閉該文件后才能刪除。因此,在Close系統(tǒng)調(diào)用中還要增加如下內(nèi)容:若文件關(guān)閉后它在全局文件表中已經(jīng)不存在且文件名在刪除隊列中,則此時執(zhí)行刪除文件操作,并將文件從刪除隊列中移出。1.1.3關(guān)鍵點與難點
注意:以上系統(tǒng)調(diào)用只是在一般情況下函數(shù)的執(zhí)行流程。為了提高系統(tǒng)的健壯性,在系統(tǒng)調(diào)用中還要進行下列錯誤檢查:a)文件名長度不得超過256字符,不得含有非法字符或空。b)打開,創(chuàng)建文件時,局部描述符表不能滿。c)fileSystem的操作返回值必須正確。d)readVirtualMemory和writeVirtualMemory的返回值必須正確。1.1.4實現(xiàn)代碼 privateinthandleCreate(intfileAddress){ //限定文件名長度,readVirtualMemoryString讀取文件名 Stringfilename=readVirtualMemoryString(fileAddress,256); if(filename==null) return-1; intfileDescriptor=findEmpty(); if(fileDescriptor==-1) return-1; else{ //ThreadedKernel.fileSystem.open()打開文件(第二個參數(shù)為true表示創(chuàng)建新文件) openfile[fileDescriptor]=ThreadedKernel.fileSystem.open(filename, true); returnfileDescriptor; } } privateinthandleOpen(intfileAddress){ //限定文件名長度 Stringfilename=readVirtualMemoryString(fileAddress,256); if(filename==null) return-1; intfileDescriptor=findEmpty(); //為空,報錯。 if(fileDescriptor==-1) return-1; else{openfile[fileDescriptor]=ThreadedKernel.fileSystem.open(filename, false); returnfileDescriptor; } }privateinthandleRead(intfileDescriptor,intbufferAddress,intlength){ //如果打開文件大于16個或者小于0個,或者打開文件列表為空,直接返回。 if(fileDescriptor>15||fileDescriptor<0 ||openfile[fileDescriptor]==null) return-1; bytetemp[]=newbyte[length]; //通過OpenFile.read讀取文件內(nèi)容 intreadNumber=openfile[fileDescriptor].read(temp,0,length); if(readNumber<=0) return0; //把該數(shù)據(jù)寫入虛擬內(nèi)存。 intwriteNumber=writeVirtualMemory(bufferAddress,temp); returnwriteNumber; } privateinthandleWrite(intfileDescriptor,intbufferAddress,intlength){ //如果打開文件大于16個或者小于0個,或者打開文件列表為空,直接返回。 if(fileDescriptor>15||fileDescriptor<0 ||openfile[fileDescriptor]==null) return-1;//文件未打開,出錯 //創(chuàng)建數(shù)組temp,把虛擬內(nèi)存中的內(nèi)容讀入temp,得到讀出數(shù)據(jù)長度 bytetemp[]=newbyte[length]; intreadNumber=readVirtualMemory(bufferAddress,temp); //若讀出數(shù)據(jù)小于0即為出錯,返回。 if(readNumber<=0) return0; //把該數(shù)據(jù)寫入磁盤。 intwriteNumber=openfile[fileDescriptor].write(temp,0,length); //若寫的數(shù)據(jù)長度小于讀出的數(shù)據(jù)長度,則錯誤,返回錯誤代碼 if(writeNumber<length) return-1; //返回寫入文件的字節(jié)數(shù) returnwriteNumber; } privateinthandleClose(intfileDescriptor){ //如果打開文件大于16個或者小于0個,或者打開文件列表為空,直接返回。 if(fileDescriptor>15||fileDescriptor<0 ||openfile[fileDescriptor]==null) //文件不存在,關(guān)閉出錯 return-1; //否則關(guān)閉,把openfile數(shù)組中fileDescriptor中的位置置為0 openfile[fileDescriptor].close(); openfile[fileDescriptor]=null; return0; } privateinthandleUnlink(intfileAddress){ //根據(jù)傳入的fileAddress,從虛擬內(nèi)存中讀出文件名。 Stringfilename=readVirtualMemoryString(fileAddress,256); //如果不存在,不必刪除 if(filename==null) return0; //如果存在,就刪除,出錯返回錯誤代碼 if(ThreadedKernel.fileSystem.remove(filename)) return0; else return-1; }1.2Task
2.2完成對多道程序的支持
1.2.1題目要求完成對多道程序的支持。已給出的代碼只能一次運行一個進程,而你要使它支持多道程序。從分配物理內(nèi)存入手,不同的進程在在內(nèi)存使用上不會重疊。用戶程序不會使用malloc()或free(),既用戶沒有動態(tài)內(nèi)存分配的需求。也就是說當(dāng)進程創(chuàng)建,你完全知道它需要的內(nèi)存大小,你要為進程棧分配合適的頁大小,8頁就足夠了。建議保持空閑物理頁的全局鏈接列表(UserKernelclass的一部分),訪問列表時會用到同步。解決方案為新進程分配頁時務(wù)必有效的使用內(nèi)存。只在連續(xù)塊上分配內(nèi)存是不可取的的,你的方案必須用到空閑內(nèi)存池中的縫隙。保持每個進程的頁表,頁表保持了用戶虛擬地址到物理地址的映射。TranslationEntryclass代表了一個虛擬到物理的頁轉(zhuǎn)換。如果頁來自COFFsection,那么在TranslationEntry.readOnly文件中要將其標記為只讀。這個方法失敗不會拋出異常,它總會返回傳送的位數(shù),即使是零。修改UserProcess.loadSections(),根據(jù)所需為進程分配頁數(shù)。用你決定的分配規(guī)則。這個方法還要為進程開啟頁表structure,這樣進程就被加載到當(dāng)前物理內(nèi)存頁中。1.2.2題目分析與實現(xiàn)方案Nachos為不同進程應(yīng)分配完全不同的物理內(nèi)存,但不支持動態(tài)內(nèi)存分配,所以需要分配的內(nèi)存在裝入程序時就可以確定了(代碼,數(shù)據(jù),堆棧部分)。故在裝入程序時就為每個進程一次性分配固定的物理內(nèi)存,在進程結(jié)束時收回它們。這里還需要實現(xiàn)如下簡單的虛擬內(nèi)存方案:每個進程的地址空間是連續(xù)的虛擬內(nèi)存,但這些連續(xù)的虛擬頁面在物理內(nèi)存中卻不一定是連續(xù)的。這個方案的簡單之處在于,虛擬空間的總?cè)萘亢臀锢砜臻g的總?cè)萘肯嗟?映射機制只是從虛擬內(nèi)存到物理內(nèi)存的一一映射。除了內(nèi)存的分配,內(nèi)存的讀寫也要體現(xiàn)出映射機制。方案:頁表pageTable以虛擬頁號為下標,其中的每個項目是一個machine.TranslationEntry類型的對象,存放了一個頁的下列信息:物理頁號,虛擬頁號,是否有效,是否只讀,是否被用過,是否臟。在UserKernel中定義一個全局隊列memoryLinkedList用于存放當(dāng)前空閑的物理頁號,一個保護內(nèi)存互斥訪問的鎖allocateMemoryLock。開始時,memoryLinkedList包括所有的物理頁面。當(dāng)啟動新進程時,UserProcess.load負責(zé)從磁盤裝入進程。過程UserProcess.loadSections完成如下操作:先獲得allocateMemoryLock,鎖定內(nèi)存。該進程需要的頁面數(shù)已知,保存在numPage變量中。與memoryLinkedList比較,判斷空余存儲空間是否足夠。分配物理頁(UserKernel.allocatePages)時從memoryLinkedList中出隊相應(yīng)數(shù)量的頁面(返回的是物理頁號的數(shù)組)。2)整個需要裝入的進程是一個machine.CoffSection類型的對象,包括若干個頁。在loadSection中,在釋放allocateMemoryLock前應(yīng)該創(chuàng)建一個頁表。3)得到可用的物理頁號后,就裝入所有的頁,為段中每個虛擬頁在pageTable中創(chuàng)建一個新的TranslationEntry對象并為其賦上相應(yīng)的虛擬頁號和物理頁號等信息,然后將原來section對象的讀寫權(quán)限等轉(zhuǎn)移,然后并調(diào)用CoffSection.loadPage將頁的內(nèi)容讀入。讀入時進行物理地址和邏輯地址的關(guān)聯(lián),然后把程序的每一塊按照順序?qū)?yīng)于物理地址導(dǎo)入到內(nèi)存中。完成了題目的“保持物理頁的全局鏈接表”的要求。4)在進程結(jié)束時,對于頁表中所有的頁面,只要將其虛擬頁號放入memoryLinkedList隊列。UserProcess.readVirtualMemory讀虛擬內(nèi)存。讀內(nèi)存時,要先利用頁表將邏輯地址轉(zhuǎn)換為物理地址然后再將內(nèi)存數(shù)據(jù)復(fù)制到數(shù)組中。類似地,UserProcess.writeVirtualMemory寫虛擬內(nèi)存,其方法與readVirtualMemory類似,要先利用頁表將邏輯地址轉(zhuǎn)換為物理地址然后再將數(shù)組數(shù)據(jù)復(fù)制到內(nèi)存中,并注意取頁面時要檢查頁面是否為只讀。1.2.3關(guān)鍵點與難點在loadSection中,在導(dǎo)入coff之前應(yīng)該創(chuàng)建一個頁表,進行物理地址和邏輯地址的關(guān)聯(lián),然后把程序的每一塊按照順序?qū)?yīng)于物理地址導(dǎo)入到內(nèi)存中。這樣就完成了題目的“保持物理頁的全局鏈接表”的要求。讀寫內(nèi)存時,要先利用頁表將邏輯地址轉(zhuǎn)換為物理地址然后再將內(nèi)存數(shù)據(jù)復(fù)制到數(shù)組中,取頁面時要檢查頁面是否為只讀。。讀寫內(nèi)存時要注意判斷內(nèi)存是否已滿,數(shù)組是否已滿,是否有錯誤參數(shù)(比如寫入數(shù)據(jù)的長度<0),另外題目要求無論讀寫是否成功都不報錯,而是返回讀寫數(shù)據(jù)的長度。1.2.4實現(xiàn)代碼UserKernel://保護內(nèi)存互斥訪問的鎖 publicstaticLockallocateMemoryLock; //全局隊列,用于存放當(dāng)前空閑的物理頁號publicstaticLinkedList<Integer>memoryLinkedList;UserProcess:protectedbooleanloadSections(){ //獲取分配內(nèi)存的鎖,鎖定內(nèi)存 UserKernel.allocateMemoryLock.acquire(); //判斷能否裝載 if(numPages>UserKernel.memoryLinkedList.size()){ coff.close(); Lib.debug(dbgProcess,"\tinsufficientphysicalmemory"); UserKernel.allocateMemoryLock.release(); //返回裝載失敗 returnfalse; } //創(chuàng)建頁表 pageTable=newTranslationEntry[numPages]; for(inti=0;i<numPages;i++){ intnextPage=UserKernel.memoryLinkedList.remove(); pageTable[i]=newTranslationEntry(i,nextPage,true,false, false,false); } //釋放鎖 UserKernel.allocateMemoryLock.release(); for(ints=0;s<coff.getNumSections();s++){ CoffSectionsection=coff.getSection(s); //獲得section Lib.debug(dbgProcess,"\tinitializing"+section.getName() +"section("+section.getLength()+"pages)"); for(inti=0;i<section.getLength();i++){ intvpn=section.getFirstVPN()+i; //標記只為已讀 pageTable[vpn].readOnly=section.isReadOnly(); section.loadPage(i,pageTable[vpn].ppn); } } returntrue; }publicintreadVirtualMemory(intvaddr,byte[]data,intoffset,intlength){ //保證偏移量與長度都為正,偏移量+長度<=總的數(shù)據(jù)長度 Lib.assertTrue(offset>=0&&length>=0 &&offset+length<=data.length); byte[]memory=Mcessor().getMemory();//獲得需求 if(length>(pageSize*numPages-vaddr))//判斷能否讀取 length=pageSize*numPages-vaddr; if(data.length-offset<length) length=data.length-offset; inttransferredbyte=0; do{ intpageNum=Processor.pageFromAddress(vaddr+transferredbyte); if(pageNum<0||pageNum>=pageTable.length) return0; intpageOffset=Processor.offsetFromAddress(vaddr +transferredbyte); intleftByte=pageSize-pageOffset; intamount=Math.min(leftByte,length-transferredbyte); intrealAddress=pageTable[pageNum].ppn*pageSize+pageOffset; System.arraycopy(memory,realAddress,data,offset +transferredbyte,amount); transferredbyte=transferredbyte+amount; }while(transferredbyte<length); returntransferredbyte;}publicintwriteVirtualMemory(intvaddr,byte[]data,intoffset,intlength){ Lib.assertTrue(offset>=0&&length>=0 &&offset+length<=data.length); byte[]memory=Mcessor().getMemory(); if(length>(pageSize*numPages-vaddr)) length=pageSize*numPages-vaddr; if(data.length-offset<length) length=data.length-offset; inttransferredbyte=0; do{ intpageNum=Processor.pageFromAddress(vaddr+transferredbyte); if(pageNum<0||pageNum>=pageTable.length) return0; intpageOffset=Processor.offsetFromAddress(vaddr +transferredbyte); intleftByte=pageSize-pageOffset; intamount=Math.min(leftByte,length-transferredbyte); intrealAddress=pageTable[pageNum].ppn*pageSize+pageOffset; System.arraycopy(data,offset+transferredbyte,memory, realAddress,amount); transferredbyte=transferredbyte+amount; }while(transferredbyte<length); returntransferredbyte;}1.3
Task
2.3
實現(xiàn)系統(tǒng)調(diào)用1.3.1題目要求實現(xiàn)系統(tǒng)調(diào)用(exec,join,andexit,同樣在syscall.h)。此外,所有通過寄存器來Exec和加入的地址是虛擬地址。你應(yīng)該使用readVirtualMemory和readVirtualMemoryString在內(nèi)核和用戶進程之間傳遞內(nèi)存。同樣,你必須防止這些系統(tǒng)調(diào)用。注意,子過程的狀態(tài)是進程完全私有的。這意味著,父進程和子進程不直接共享存儲器或文件描述符。注意兩個過程當(dāng)然可以打開相同的文件;例如,所有的進程應(yīng)該有的0和1映射到系統(tǒng)控制臺的文件描述符。不像KThread.join(),只有一個進程的父進程可以調(diào)用join()。舉例來說,如果A創(chuàng)建B并且B創(chuàng)建C,A不允許join()到C中,但B被允許join()到C。加入需要一個進程ID作為參數(shù),用于唯一標識其父母希望加入的子進程。進程ID應(yīng)該是全局唯一的正整數(shù),在每個進程創(chuàng)建時分配。(雖然在這個項目的唯一使用的進程ID是在join(),進程ID是整個系統(tǒng)中的所有正在運行的進程是唯一的以后項目階段很重要)。解決這個問題的最簡單的方法就是保持一個表明接下來的進程ID分配的靜止計數(shù)器。由于該進程ID是int類型,則有可能對是否存在在系統(tǒng)中的許多過程這個值溢出。對于這個項目,你不必要處理這種情況下,也就是說,假定該方法ID計數(shù)器不會溢出。當(dāng)進程調(diào)用exit(),它的線程應(yīng)立即終止,而這個過程應(yīng)該清理與它相關(guān)的任何狀態(tài)(也就是釋放內(nèi)存,關(guān)閉打開的文件等)。如果一個進程異常退出執(zhí)行相同的清理。在退出過程的退出狀態(tài)應(yīng)轉(zhuǎn)移到父進程,如果父調(diào)用join()系統(tǒng)調(diào)用。一個進程退出狀態(tài)的異常與否取決于你。對于join()的目的,如果它任何狀態(tài)下調(diào)用退出函數(shù),那么一個子進程正常退出,如果內(nèi)核殺死它(例如,由于未處理的異常)則是不正常的。最后一個過程調(diào)用exit()應(yīng)使machine類暫停,通過Kernel.kernel.terminate()(請注意,只有根進程中應(yīng)允許調(diào)用halt()系統(tǒng)調(diào)用,但最后退出的過程中應(yīng)該直接調(diào)用Kernel.kernel.terminate()1.3.2題目分析與實現(xiàn)方案在該系統(tǒng)調(diào)用中,第一個參數(shù)為文件名地址,第二個參數(shù)為參數(shù)個數(shù),第三個參數(shù)為參數(shù)表指針.需要做的工作是:讀虛擬內(nèi)存獲得文件名2.處理參數(shù)。首先用第三個參數(shù)作為虛擬內(nèi)存地址得到參數(shù)表數(shù)組的首址,然后用readVirtualMemoryString依次讀出每個參數(shù)3.用UserProcess.newUserProcess創(chuàng)建子進程,將文件和參數(shù)表加載到子進程4.用UserProcess.execute方法執(zhí)行子進程,同時將這個子進程的父進程置為這個進程,再將子進程加入子進程列表join:該系統(tǒng)調(diào)用中,第一個參數(shù)為子進程編號,第二個參數(shù)一個地址,用于保存子進程的返回值.需要做的工作是:1.利用進程號確定join的是哪一個進程,檢查childProcesses,遍歷子進程鏈表,確定join的進程是子進程。如果子進程編號不在其中則出錯返回2.獲得join鎖,讓該進程休眠,直到子進程喚醒3.子進程喚醒之后,將子進程的狀態(tài)存入自己的內(nèi)存中,判斷當(dāng)前進程是否正常結(jié)束。結(jié)束則返回。exit:首先關(guān)閉coff,然后將所有的打開文件關(guān)閉,把退出的狀態(tài)置入,如果該進程有父進程,看是否執(zhí)行了join方法,如果執(zhí)行就將其喚醒,同時將本進程從子進程鏈表中刪除,釋放內(nèi)存,結(jié)束底層線程,如果是最后一個結(jié)束的進程則將系統(tǒng)關(guān)閉。該系統(tǒng)調(diào)用的唯一參數(shù)為返回值。需要做的工作為:1.關(guān)閉coff,關(guān)閉所有打開的文件,把退出的狀態(tài)置入2.如果該進程有父進程,看是否執(zhí)行了join方法,如果執(zhí)行就將其喚醒,同時將此進程從子進程鏈表中刪除3.調(diào)用unloadsections釋放內(nèi)存,調(diào)用KThread.finish方法結(jié)束當(dāng)前線程4.如果是最后一個進程,調(diào)用Machine.halt()停機,修改運行的進程總數(shù)1.3.3關(guān)鍵點與難點exec()實現(xiàn)創(chuàng)建子進程并執(zhí)行功能,涉及執(zhí)行程序地址,參數(shù)數(shù)量,參數(shù)地址相關(guān)參數(shù),并返回子進程id。join()阻塞等待某子進程執(zhí)行完畢;涉及參數(shù)子進程id,子進程地址,并返回-1/0/1exit()關(guān)閉進程,清除相關(guān)信息,涉及進程狀態(tài)參數(shù),返回0.應(yīng)注意:1)父進程和子進程不共享任何的內(nèi)存,文件或其它狀態(tài)。2)只有父進程能對子進程進行join操作。例如A執(zhí)行B,B執(zhí)行C,則A不允許joinC,而B允許joinC。3)需要為每個進程分配一個唯一的進程編號。4)exit操作將使當(dāng)前進程立即結(jié)束,如果父進程對其進行join操作,返回代碼這時應(yīng)返回。5)最后一個調(diào)用exit的進程將使系統(tǒng)停機1.3.4實現(xiàn)代碼 UserProcessparentProcess; LinkedList<UserProcess>childProcess; privateKThreadthread; privateLockjoinLock; ConditionjoinCondition; intnumOfRunningProcess; privatebooleannormalExit; privateintstatus; privateintpid;privateinthandleExec(intfileAddress,intargc,intargvAddress){ //文件名大小,讀虛擬內(nèi)存獲得文件名 Stringfilename=readVirtualMemoryString(fileAddress,256); //文件出錯 if(filename==null||argc<0||argvAddress<0 ||argvAddress>numPages*pageSize) return-1; String[]args=newString[argc]; //將文件內(nèi)容讀入虛擬內(nèi)存 for(inti=0;i<argc;i++){ byte[]argsAddress=newbyte[4]; if(readVirtualMemory(argvAddress+i*4,argsAddress)>0) args[i]=readVirtualMemoryString( Lib.bytesToInt(argsAddress,0),256); } //創(chuàng)建子進程,將文件和參數(shù)表加載到子進程 UserProcessprocess=UserProcess.newUserProcess(); //文件打開失敗,退出 if(!process.execute(filename,args)) return-1; //將當(dāng)前父進程信息賦予子進程 process.parentProcess=this; childProcess.add(process); //返回子進程編號 returnprocess.pid; } privateinthandleJoin(intpid,intstatusAddress){ UserProcessprocess=null; //利用進程號確定join的是哪一個進程 for(inti=0;i<childProcess.size();i++){ //如果子進程是當(dāng)前運行程序,則返回 if(pid==childProcess.get(i).pid){ process=childProcess.get(i); break; } } if(process==null||process.thread==null) return-1; //得到鎖 process.joinLock.acquire(); //進程睡眠 process.joinCondition.sleep(); process.joinLock.release(); byte[]childstat=newbyte[4]; Lib.bytesFromInt(childstat,0,process.status); //將要寫入虛擬內(nèi)存大小 intnumWriteByte=writeVirtualMemory(statusAddress,childstat); if(process.normalExit&&numWriteByte==4) return1; return0; } privateinthandleExit(intstatus){ //關(guān)閉coff區(qū) coff.close(); //關(guān)閉所有打開的文件 for(inti=0;i<16;i++){ //無內(nèi)容可寫,關(guān) if(openfile[i]!=null){ openfile[i].close(); openfile[i]=null; } } this.status=status; //把退出的狀態(tài)置入 normalExit=true; //運行權(quán)還給父進程 if(parentProcess!=null){ //實現(xiàn)互斥 joinLock.acquire(); joinCondition.wake(); joinLock.release(); parentProcess.childProcess.remove(this); } //釋放內(nèi)存 unloadSections(); //結(jié)束當(dāng)前線程 KThread.finish(); //如果是最后一個進程,調(diào)用Machine.halt()停機 if(numOfRunningProcess==1) Machine.halt(); //修改運行的進程總數(shù) numOfRunningProcess--; return0; }1.4Task2.4實現(xiàn)彩票調(diào)度1.4.1題目要求實現(xiàn)彩票調(diào)度(把它放在線程/LotteryScheduler.java)。注意,這個類擴展自PriorityScheduler,你應(yīng)該能夠重復(fù)使用的大部分該類的功能;彩票調(diào)度應(yīng)是大量的額外的代碼。唯一的主要區(qū)別是程序從隊列機制挑選一個線程:彩票是持有,而不是僅僅選取優(yōu)先級最高的線程。你的彩票調(diào)度應(yīng)實施優(yōu)先級優(yōu)先捐贈。(請注意,因為這是一個彩票調(diào)度,優(yōu)先級反轉(zhuǎn)實際上并不能導(dǎo)致饑餓!但是,你必須做優(yōu)先權(quán)捐贈)在彩票調(diào)度中,除了優(yōu)先權(quán)的捐助,等待線程轉(zhuǎn)移門票給他們等待的線程。不同于標準的優(yōu)先級調(diào)度,一個等待線程總是將其門票給隊列所有者;即,擁有者的門票數(shù)是它自己的門票的總和與所有服務(wù)員的票,而不是最大值。一定要正確地實現(xiàn)這一點。你的解決方案應(yīng)該工作,即使有幾十億的門票系統(tǒng)(即不保持包含每票項的數(shù)組)。當(dāng)LotteryScheduler.increasePriority()被調(diào)用時,由一個進程擁有的彩票數(shù)目遞增。同樣地,對于decreasePriority(),該數(shù)量應(yīng)該減一。車票中系統(tǒng)中的車票總數(shù)目是保證不超過Integer.MAX_VALUE的。現(xiàn)在設(shè)置的最高優(yōu)先級也是Integer.MAX_VALUE,而不是7(PriorityScheduler.priorityMaximum)。如果你愿意,你也可以假設(shè)最小的優(yōu)先級提高到1(從0)。1.4.2題目分析與實現(xiàn)方案具體過程大體為:1.統(tǒng)計總的彩票數(shù)2.生成合理中獎彩票找出持有者->調(diào)度引入一個ThreadState類用來把進程和彩票數(shù)量聯(lián)系在一起,但是在得到有效優(yōu)先級時,是把等待自己的隊列中的進程的優(yōu)先級和自己的優(yōu)先級加起來,總的彩票數(shù)才是自己的優(yōu)先級。在getEffectivePriorityNachos中將選取最大優(yōu)先級的過程改成將所有等待線程的優(yōu)先級(彩票數(shù))加到lockHolder上(即等待者把自己擁有的彩票給獲得鎖的線程),其次將nextThread修改如下:首先遍歷一遍隊列,計算出當(dāng)前隊列中的所有隊列的彩票總數(shù)(考慮過donation后的)numEf
溫馨提示
- 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2020-2021深圳寶文學(xué)校小學(xué)三年級數(shù)學(xué)下期末第一次模擬試卷(及答案)
- 人教版(2024)七年級英語下冊Unit 7 單元檢測試卷(含答案)
- 甘肅木屋別墅施工方案
- 折扣(教學(xué)設(shè)計)-2023-2024學(xué)年六年級下冊數(shù)學(xué)人教版
- 統(tǒng)戰(zhàn)理論知識培訓(xùn)班課件
- 知識產(chǎn)權(quán)業(yè)務(wù)培訓(xùn)課件
- 云南省麗江市華坪縣2025屆中考五模生物試題含解析
- epc合作內(nèi)部合同范例
- 財務(wù)共享服務(wù)中心的構(gòu)建計劃
- 公司合同范例填
- 安全生產(chǎn)費用歸集清單(安措費清單)
- 中小學(xué)生心理健康檔案(表格)電子教案
- 廣東省五年一貫制語文考試題目
- 江蘇省南京市2023屆高三第一學(xué)期期初考試英語試題和答案
- 10kV電力線路改造工程量清單
- 紅樓春趣劇本新編
- FLUX系統(tǒng)用戶手冊
- WB/T 1066-2017貨架安裝及驗收技術(shù)條件
- GB/T 40806-2021機床發(fā)射空氣傳播噪聲金屬切削機床的操作條件
- 打起手鼓唱起歌二聲部改編簡譜
- 新外研版高二英語選擇性必修二unit6 PlanB life on Mars 課件
評論
0/150
提交評論