Nachos線程通信和調(diào)度分析操作系統(tǒng)課程設(shè)計(jì)說明書_第1頁
Nachos線程通信和調(diào)度分析操作系統(tǒng)課程設(shè)計(jì)說明書_第2頁
Nachos線程通信和調(diào)度分析操作系統(tǒng)課程設(shè)計(jì)說明書_第3頁
Nachos線程通信和調(diào)度分析操作系統(tǒng)課程設(shè)計(jì)說明書_第4頁
Nachos線程通信和調(diào)度分析操作系統(tǒng)課程設(shè)計(jì)說明書_第5頁
已閱讀5頁,還剩71頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、操作系統(tǒng)課程設(shè)計(jì)說 明 書學(xué) 院: 信息科學(xué)與工程學(xué)院 TOC o 1-3 h u HYPERLINK l _Toc13669 一、 理解Nachos模擬的物理機(jī)的運(yùn)行機(jī)制 PAGEREF _Toc13669 3 HYPERLINK l _Toc7854 1. Sysdep模塊分析(文件) PAGEREF _Toc7854 5 HYPERLINK l _Toc25559 2.中斷模塊分析(文件) PAGEREF _Toc25559 10 HYPERLINK l _Toc17859 3. 時(shí)鐘中斷模塊分析(文件) PAGEREF _Toc17859 16 HYPERLINK l _Toc1189

2、2 4. 終端設(shè)備模塊分析(文件) PAGEREF _Toc11892 18 HYPERLINK l _Toc8435 二、 理解Nachos中線程運(yùn)行機(jī)制 PAGEREF _Toc8435 19 HYPERLINK l _Toc31733 1. 工具模塊分析(文件) PAGEREF _Toc31733 20 HYPERLINK l _Toc27361 2. 線程啟動(dòng)和調(diào)度模塊分析(文件) PAGEREF _Toc27361 21 HYPERLINK l _Toc6132 3. 線程模塊分析(文件) PAGEREF _Toc6132 22 HYPERLINK l _Toc30243 4. 線程

3、調(diào)度算法模塊分析(文件) PAGEREF _Toc30243 26 HYPERLINK l _Toc29328 5.Nachos主控模塊分析(文件) PAGEREF _Toc29328 27 HYPERLINK l _Toc8913 6. 同步機(jī)制模塊分析(文件) PAGEREF _Toc8913 28 HYPERLINK l _Toc8740 三、 理解Nachos中支持用戶進(jìn)程的機(jī)制 PAGEREF _Toc8740 30 HYPERLINK l _Toc24555 一、用戶程序空間(文件address.cc, address.h) PAGEREF _Toc24555 35 HYPERLI

4、NK l _Toc27544 二、系統(tǒng)調(diào)用(文件exception.cc, syscall.h, start.s) PAGEREF _Toc27544 36理解Nachos模擬的物理機(jī)的運(yùn)行機(jī)制Machine類 XE Machine類 用來模擬計(jì)算機(jī)主機(jī)。它提供的功能有:讀寫寄存器。讀寫主存、運(yùn)行一條用戶程序 XE 用戶程序 的匯編指令、運(yùn)行用戶程序、單步調(diào)試用戶程序、顯示主存和寄存器狀態(tài)、將虛擬內(nèi)存 XE 虛擬內(nèi)存 地址轉(zhuǎn)換為物理內(nèi)存地址、陷入 Nachos 內(nèi)核等等。Machine類 XE Machine類 實(shí)現(xiàn)方法是在宿主機(jī)上分配兩塊內(nèi)存分別作為虛擬機(jī)的寄存器和物理內(nèi)存。運(yùn)行用戶程序 X

5、E 用戶程序 時(shí),先將用戶程序從 Nachos 文件系統(tǒng)中讀出,寫入模擬的物理內(nèi)存中,然后調(diào)用指令模擬模塊對(duì)每一條用戶指令解釋執(zhí)行。將用戶程序的讀寫內(nèi)存要求,轉(zhuǎn)變?yōu)閷?duì)物理內(nèi)存地址的讀寫。Machine類提供了單步調(diào)試用戶程序的功能,執(zhí)行一條指令后會(huì)自動(dòng)停下來,讓用戶查看系統(tǒng)狀態(tài),不過這里的單步調(diào)試是匯編指令級(jí)的,需要讀者對(duì)R2/3000 XE R2/3000 指令比較熟悉。如果用戶程序想使用操作系統(tǒng)提供的功能或者發(fā)出異常信號(hào)時(shí),Machine調(diào)用系統(tǒng)異常陷入功能,進(jìn)入Nachos的核心部分。Interrupt類 XE Interrupt類 用來模擬硬件中斷系統(tǒng)。在這個(gè)中斷系統(tǒng)中,中斷狀態(tài)有開,

6、關(guān)兩種,中斷類型有時(shí)鐘中斷、磁盤中斷、控制臺(tái)寫中斷、控制臺(tái)讀中斷、網(wǎng)絡(luò)發(fā)送中斷以及網(wǎng)絡(luò)接收中斷。機(jī)器狀態(tài)有用戶態(tài),核心態(tài)和空閑態(tài)。中斷系統(tǒng)提供的功能有開/關(guān)中斷,讀/寫機(jī)器狀態(tài),將一個(gè)即將發(fā)生中斷放入中斷隊(duì)列,以及使機(jī)器時(shí)鐘前進(jìn)一步。在Interrupt類 XE Interrupt類 中有一個(gè)記錄即將發(fā)生中斷的隊(duì)列,稱為中斷等待隊(duì)列。中斷等待隊(duì)列中每個(gè)等待處理的中斷包含中斷類型、中斷處理程序的地址及參數(shù)、中斷應(yīng)當(dāng)發(fā)生的時(shí)間等信息。一般是由硬件設(shè)備模擬程序把將要發(fā)生的中斷放入中斷隊(duì)列。中斷系統(tǒng)提供了一個(gè)模擬機(jī)器時(shí)鐘,機(jī)器時(shí)鐘在下列情況下前進(jìn):用戶程序 XE 用戶程序 打開中斷執(zhí)行一條用戶指令處理

7、機(jī)沒有進(jìn)程正在運(yùn)行機(jī)器時(shí)鐘前進(jìn)時(shí),中斷處理的過程如下圖所示:Nachos中斷處理時(shí)機(jī)NYNY進(jìn)行正文切換中斷處理程序要求進(jìn)行正文切換?開中斷取出隊(duì)列中一個(gè)應(yīng)當(dāng)發(fā)生的中斷,調(diào)用這個(gè)中斷的處理程序去處理中斷中斷隊(duì)列中有應(yīng)當(dāng)發(fā)生的中斷?關(guān)中斷中斷系統(tǒng)成為整個(gè)Nachos虛擬機(jī)的基礎(chǔ),其它的模擬硬件設(shè)備都是建立在中斷系統(tǒng)之上的。在此之上,加上Machine類 XE Machine類 模擬的指令解釋器,可以實(shí)現(xiàn)Nachos的線程管理 XE 線程管理 、文件系統(tǒng)管理 XE 文件系統(tǒng)管理 、虛擬內(nèi)存 XE 虛擬內(nèi)存 、用戶程序 XE 用戶程序 和網(wǎng)絡(luò)管理 XE 網(wǎng)絡(luò)管理 等所有操作系統(tǒng)功能。下圖展示了Nac

8、hos系統(tǒng)的整體結(jié)構(gòu)。用 戶 程 序線程管理 XE 線程管理 網(wǎng)絡(luò)協(xié)議文件系統(tǒng)虛擬內(nèi)存 XE 虛擬內(nèi)存 終端設(shè)備時(shí)鐘網(wǎng)絡(luò)磁盤中 斷 系 統(tǒng)指令解釋和內(nèi)存模擬Nachos系統(tǒng)的整體結(jié)構(gòu)機(jī)器模擬的實(shí)現(xiàn):1. Sysdep模塊分析(文件)Nachos的運(yùn)行環(huán)境可以是多種操作系統(tǒng),由于每種操作系統(tǒng)所提供的系統(tǒng)調(diào)用或函數(shù)調(diào)用在形式和內(nèi)容上可能有細(xì)微的差別。sysdep模塊的作用是屏蔽掉這些差別。1.1 PoolFile 函數(shù)語法:bool PoolFile (int fd)參數(shù):fd:文件描述符,也可以是一個(gè)套接字 (socket)功能:測(cè)試一個(gè)打開文件 fd 是否有內(nèi)容可以讀,如果有則返回TRUE,否

9、則返回FALSE。當(dāng)Nachos系統(tǒng)處于IDLE狀態(tài)時(shí),測(cè)試過程有一個(gè)延時(shí),也就是在一定時(shí)間范圍內(nèi)如果有內(nèi)容可讀的話,同樣返回TRUE。實(shí)現(xiàn):通過 select 系統(tǒng)調(diào)用。返回:打開文件是否有內(nèi)容供讀取。1.2 OpenForWrite 函數(shù)語法:int OpenForWrite (char *name)參數(shù):name:文件名功能:為寫操作打開一個(gè)文件。如果該文件不存在,產(chǎn)生該文件;如果該文件已經(jīng)存在,則將該文件原有的內(nèi)容刪除。實(shí)現(xiàn):通過 open 系統(tǒng)調(diào)用。返回:打開的文件描述符。1.3 OpenForReadWrite 函數(shù)語法:int OpenForReadWrite (char *na

10、me, bool crashOnError)參數(shù):name:文件名crashOnError:crash標(biāo)志功能:為讀寫操作打開一個(gè)文件。當(dāng) crashOnError 標(biāo)志設(shè)置而文件不能讀寫打開時(shí),系統(tǒng)出錯(cuò)退出。實(shí)現(xiàn):通過 open 系統(tǒng)調(diào)用。返回:打開的文件描述符。1.4 Read 函數(shù)語法:void Read (int fd, char *buffer, int nBytes)參數(shù):fd:打開文件描述符buffer:讀取內(nèi)容的緩沖區(qū)nBytes:需要讀取的字節(jié)數(shù)功能:從一個(gè)打開文件fd中讀取nBytes的內(nèi)容到buffer緩沖區(qū)。如果讀取失敗,系統(tǒng)退出。實(shí)現(xiàn):通過 read系統(tǒng)調(diào)用。返回:空

11、。1.5 ReadPartial 函數(shù)語法:int ReadPartial (int fd, char *buffer, int nBytes)參數(shù):fd:打開文件描述符buffer:讀取內(nèi)容的緩沖區(qū)nBytes:需要讀取的最大字節(jié)數(shù) 功能:從一個(gè)打開文件fd中讀取nBytes的內(nèi)容到buffer緩沖區(qū)。 實(shí)現(xiàn):通過 read系統(tǒng)調(diào)用。 返回:實(shí)際讀出的字節(jié)數(shù)。1.6 WriteFile 函數(shù) 語法:void WriteFile (int fd, char *buffer, int nBytes) 參數(shù):fd:打開文件描述符buffer:需要寫的內(nèi)容所在的緩沖區(qū)nBytes:需要寫的內(nèi)容最大字

12、節(jié)數(shù) 功能:將buffer緩沖區(qū)中的內(nèi)容寫nBytes到一個(gè)打開文件fd中。 實(shí)現(xiàn):通過 write系統(tǒng)調(diào)用。 返回:空1.7 Lseek 函數(shù) 語法:void Lseek (int fd, int offset, int whence) 參數(shù):fd:文件描述符offset:偏移量whence:指針移動(dòng)的起始點(diǎn) 功能:移動(dòng)一個(gè)打開文件的讀寫指針,含義同lseek系統(tǒng)調(diào)用;出錯(cuò)則退出系統(tǒng)。 實(shí)現(xiàn):通過lseek 系統(tǒng)調(diào)用。 返回:空。1.8 Tell 函數(shù) 語法:int Tell (int fd) 參數(shù):fd:文件描述符 功能:指出當(dāng)前讀寫指針位置 實(shí)現(xiàn):通過lseek 系統(tǒng)調(diào)用。 返回:返回當(dāng)

13、前指針位置。1.9 Close 函數(shù) 語法:void Close (int fd) 參數(shù):fd:文件描述符 功能:關(guān)閉當(dāng)前打開文件fd,如果出錯(cuò)則退出系統(tǒng)。 實(shí)現(xiàn):通過close系統(tǒng)調(diào)用。 返回:空1.10 Unlink 函數(shù) 語法:bool Unlink (char *name) 參數(shù):name:文件名 功能:刪除文件。 實(shí)現(xiàn):通過unlink系統(tǒng)調(diào)用。 返回:刪除成功,返回TRUE;否則返回FALSE。1.11 OpenSocket 函數(shù) 語法:int OpenSocket () 參數(shù):無 功能:申請(qǐng)一個(gè)socket。 實(shí)現(xiàn):通過socket系統(tǒng)調(diào)用。其中AF_UNIX參數(shù)說明使用UNIX

14、內(nèi)部協(xié)議。(Nachos是用SOCKET文件來模擬網(wǎng)絡(luò)節(jié)點(diǎn),所以采用UNIX內(nèi)部協(xié)議。向該文件讀寫內(nèi)容分別代表從該節(jié)點(diǎn)讀取內(nèi)容和向該網(wǎng)絡(luò)節(jié)點(diǎn)發(fā)送內(nèi)容)SOCK_DGRAM參數(shù)說明采用無連接定長(zhǎng)數(shù)據(jù)包型的數(shù)據(jù)鏈路。 返回:申請(qǐng)到的socket ID。1.12 CloseSocket 函數(shù) 語法:void CloseSocket (int sockID) 參數(shù):sockID:socket標(biāo)識(shí) 功能:釋放一個(gè)socket。 實(shí)現(xiàn):通過close系統(tǒng)調(diào)用。 返回:無。1.13 Abort 函數(shù) 語法:void Abort () 參數(shù):無 功能:退出系統(tǒng) (非正常退出)。 實(shí)現(xiàn):通過abort系統(tǒng)調(diào)用。

15、 返回:無。1.14 Exit 函數(shù) 語法:void Exit (int exitCode) 參數(shù):exitCode:向系統(tǒng)的返回值 功能:退出系統(tǒng)。 實(shí)現(xiàn):通過exit系統(tǒng)調(diào)用。 返回:空2.中斷模塊分析(文件)中斷模塊的主要作用是模擬底層的中斷機(jī)制。可以通過該模擬機(jī)制來啟動(dòng)和禁止中斷 (SetLevel);該中斷機(jī)制模擬了Nachos系統(tǒng)需要處理的所有的中斷,包括時(shí)鐘中斷、磁盤中斷、終端讀/終端寫中斷以及網(wǎng)絡(luò)接收/網(wǎng)絡(luò)發(fā)送中斷。中斷的發(fā)生總是有一定的時(shí)間。比如當(dāng)向硬盤發(fā)出讀請(qǐng)求,硬盤處理請(qǐng)求完畢后會(huì)發(fā)生中斷;在請(qǐng)求和處理完畢之間需要經(jīng)過一定的時(shí)間。所以在該模塊中,模擬了時(shí)鐘的前進(jìn)。為了實(shí)現(xiàn)

16、簡(jiǎn)單和便于統(tǒng)計(jì)各種活動(dòng)所占用的時(shí)間起見,Nachos規(guī)定系統(tǒng)時(shí)間在以下三種情況下前進(jìn):執(zhí)行用戶態(tài)指令,時(shí)鐘前進(jìn)是顯而易見的。我們認(rèn)為,Nachos執(zhí)行每條指令所需時(shí)間是固定的,為一個(gè)時(shí)鐘單位(Tick)。一般系統(tǒng)態(tài)在進(jìn)行中斷處理程序時(shí),需要關(guān)中斷。但是中斷處理程序本身也需要消耗時(shí)間,而在關(guān)閉中斷到重新打開中斷之間無法非常準(zhǔn)確地計(jì)算時(shí)間,所以當(dāng)中斷重新打開的時(shí)候,加上一個(gè)中斷處理所需時(shí)間的平均值。當(dāng)系統(tǒng)中沒有就緒進(jìn)程時(shí),系統(tǒng)處于Idle狀態(tài)。這種狀態(tài)可能是系統(tǒng)中所有的進(jìn)程都在等待各自的某種操作完成。也就是說,系統(tǒng)將在未來某個(gè)時(shí)間發(fā)生中斷,到中斷發(fā)生的時(shí)候中斷處理程序?qū)⑦M(jìn)行中斷處理。在系統(tǒng)模擬中,

17、有一個(gè)中斷等待隊(duì)列,專門存放將來發(fā)生的中斷。在這種情況下,可以將系統(tǒng)時(shí)間直接跳到中斷等待隊(duì)列第一項(xiàng)所對(duì)應(yīng)的時(shí)間,以免不必要的等待。當(dāng)前面兩種情況需要時(shí)鐘前進(jìn)時(shí),調(diào)用OneTick方法。OneTick方法將系統(tǒng)態(tài)和用戶態(tài)的時(shí)間分開進(jìn)行處理,這是因?yàn)橛脩魬B(tài)的時(shí)間計(jì)算是根據(jù)用戶指令為單位的;而在系統(tǒng)態(tài),沒有辦法進(jìn)行指令的計(jì)算,所以將系統(tǒng)態(tài)的一次中斷調(diào)用或其它需要進(jìn)行時(shí)間計(jì)算的單位設(shè)置為一個(gè)固定值,假設(shè)為一條用戶指令執(zhí)行時(shí)間的10倍。雖然Nachos模擬了中斷的發(fā)生,但是畢竟不能與實(shí)際硬件一樣,中斷發(fā)生的時(shí)機(jī)可以是任意的。比如當(dāng)系統(tǒng)中沒有就緒進(jìn)程時(shí),時(shí)鐘直接跳到未處理中斷隊(duì)列的第一項(xiàng)的時(shí)間。這實(shí)際情況

18、下,系統(tǒng)處于Idel狀態(tài)到中斷等待隊(duì)列第一項(xiàng)發(fā)生時(shí)間之間,完全有可能有其它中斷發(fā)生。由于中斷發(fā)生的時(shí)機(jī)不是完全隨機(jī)的,所以在Nachos系統(tǒng)中運(yùn)行的程序,不正確的同步程序也可能正常運(yùn)行,我們?cè)诖诵枰芮凶⒁?。Nachos線程運(yùn)行有三種狀態(tài):Idle狀態(tài)系統(tǒng)CPU處于空閑狀態(tài),沒有就緒線程可以運(yùn)行。如果中斷等待隊(duì)列中有需要處理的除了時(shí)鐘中斷以外的中斷,說明系統(tǒng)還沒有結(jié)束,將時(shí)鐘調(diào)整到發(fā)生中斷的時(shí)間,進(jìn)行中斷處理;否則認(rèn)為系統(tǒng)結(jié)束所有的工作,退出。系統(tǒng)態(tài)Nachos執(zhí)行系統(tǒng)程序。Nachos雖然模擬了虛擬機(jī)的內(nèi)存,但是Nachos系統(tǒng)程序本身的運(yùn)行不是在該模擬內(nèi)存中,而是利用宿主機(jī)的存儲(chǔ)資源。這是

19、Nachos操作系統(tǒng)同真正操作系統(tǒng)的重要區(qū)別。用戶態(tài)系統(tǒng)執(zhí)行用戶程序 XE 用戶程序 。當(dāng)執(zhí)行用戶程序時(shí),每條指令占用空間是Nachos的模擬內(nèi)存。中斷等待隊(duì)列是Nachos虛擬機(jī)最重要的數(shù)據(jù)結(jié)構(gòu)之一,它記錄了當(dāng)前虛擬機(jī)可以預(yù)測(cè)的將在未來發(fā)生的所有中斷。當(dāng)系統(tǒng)進(jìn)行了某種操作可能引起未來發(fā)生的中斷時(shí),如磁盤的寫入、向網(wǎng)絡(luò)寫入數(shù)據(jù)等都會(huì)將中斷插入到中斷等待隊(duì)列中;對(duì)于一些定期需要發(fā)生的中斷,如時(shí)鐘中斷、終端讀取中斷等,系統(tǒng)會(huì)在中斷處理后將下一次要發(fā)生的中斷插入到中斷等待隊(duì)列中。中斷的插入過程是一個(gè)優(yōu)先隊(duì)列的插入過程,其優(yōu)先級(jí)是中斷發(fā)生的時(shí)間,也就是說,先發(fā)生的中斷將優(yōu)先得到處理。對(duì)中斷等待隊(duì)列的操

20、作中斷等待隊(duì)列某些將會(huì)引起中斷的操作系統(tǒng)定期發(fā)生的中斷時(shí)鐘前進(jìn)判斷有無中斷發(fā)生當(dāng)時(shí)鐘前進(jìn)或者系統(tǒng)處于Idle狀態(tài)時(shí),Nachos會(huì)判斷中斷等待隊(duì)列中是否有要發(fā)生的中斷,如果有中斷需要發(fā)生,則將該中斷從中斷等待隊(duì)列中刪除,調(diào)用相應(yīng)的中斷處理程序進(jìn)行處理。中斷處理程序是在某種特定的中斷發(fā)生時(shí)被調(diào)用,中斷處理程序的作用包括可以在現(xiàn)有的模擬硬件的基礎(chǔ)上建立更高層次的抽象。比如現(xiàn)有的模擬網(wǎng)絡(luò)是有丟失幀的不安全網(wǎng)絡(luò),在中斷處理程序中可以加入請(qǐng)求重發(fā)機(jī)制來實(shí)現(xiàn)一個(gè)安全網(wǎng)絡(luò)。2.1 PendingInterrupt類 XE Interrupt類 class PendingInterrupt public:Pe

21、ndingInterrupt (VoidFunctionPtr func, int param, int time, IntType kind);VoidFunctionPtr handler;/ 中斷對(duì)應(yīng)的中斷處理程序int arg;/ 中斷處理程序的參數(shù)int when;/ 中斷發(fā)生的時(shí)機(jī)IntType type;/ 中斷的類型,供調(diào)試用;這個(gè)類定義了一個(gè)中斷等待隊(duì)列中需要處理的中斷。為了方便起見,所有類的數(shù)據(jù)和成員函數(shù)都設(shè)置為public的,不需要其它的Get和Set等存取內(nèi)部數(shù)據(jù)的函數(shù)。初始化函數(shù)就是為對(duì)應(yīng)的參數(shù)賦值。2.2 Interrupt類 XE Interrupt類 class

22、 Interrupt public:/ 以下函數(shù)是Interrupt的對(duì)外接口Interrupt();/ 初始化中斷模擬Interrupt();/ 終止中斷模擬IntStatus SetLevel(IntStatus level);/ 開關(guān)中斷,并且返回之前的狀態(tài)void Enable();/ 開中斷IntStatus getLevel() return level;/ 取回當(dāng)前中斷的開關(guān)狀態(tài) void Idle(); / 當(dāng)進(jìn)程就緒隊(duì)列為空時(shí),執(zhí)行該函數(shù)void Halt(); / 退出系統(tǒng),并打印狀態(tài)void YieldOnReturn();/ 設(shè)置中斷結(jié)束后要進(jìn)行進(jìn)程切換的標(biāo)志 Mach

23、ineStatus getStatus() return status; / 返回系統(tǒng)當(dāng)前的狀態(tài) void setStatus(MachineStatus st) status = st; / 設(shè)置系統(tǒng)當(dāng)前的狀態(tài) void DumpState();/ 調(diào)試當(dāng)前中斷隊(duì)列狀態(tài)用 void Schedule(VoidFunctionPtr handler, int arg, int when, IntType type);/ 在中斷等待隊(duì)列中,增加一個(gè)等待中斷 void OneTick(); / 模擬時(shí)鐘前進(jìn) private:/ 以下是內(nèi)部數(shù)據(jù)和內(nèi)部處理方法 IntStatus level;/ 中斷

24、的開關(guān)狀態(tài) List *pending;/ 當(dāng)前系統(tǒng)中等待中斷隊(duì)列bool inHandler;/ 是否正在進(jìn)行中斷處理標(biāo)志 bool yieldOnReturn; / 中斷處理后是否需要正文切換標(biāo)志MachineStatus status;/ 當(dāng)前虛擬機(jī)運(yùn)行狀態(tài)bool CheckIfDue(bool advanceClock);/ 檢查當(dāng)前時(shí)刻是否有要處理的中斷void ChangeLevel(IntStatus old, IntStatus now);/ 改變當(dāng)前中斷的開關(guān)狀態(tài),但不前進(jìn)模擬時(shí)鐘;其中,Schedule和 OneTick兩個(gè)方法雖然標(biāo)明是public的,但是除了虛擬機(jī)模擬

25、部分以外的其它類方法是不能調(diào)用這兩個(gè)方法的。將它們?cè)O(shè)置成public的原因是因?yàn)樘摂M機(jī)模擬的其它類方法需要直接調(diào)用這兩個(gè)方法。3. 時(shí)鐘中斷模塊分析(文件)該模塊的作用是模擬時(shí)鐘中斷。Nachos虛擬機(jī)可以如同實(shí)際的硬件一樣,每隔一定的時(shí)間會(huì)發(fā)生一次時(shí)鐘中斷。這是一個(gè)可選項(xiàng),目前Nachos還沒有充分發(fā)揮時(shí)鐘中斷的作用,只有在Nachos指定線程隨機(jī)切換時(shí),(Nachos -rs參數(shù),見線程管理 XE 線程管理 部分Nachos主控模塊分析)啟動(dòng)時(shí)鐘中斷,在每次的時(shí)鐘中斷處理的最后,加入了線程的切換。實(shí)際上,時(shí)鐘中斷在線程管理中的作用遠(yuǎn)不止這些,時(shí)鐘中斷還可以用作:線程管理 XE 線程管理 中

26、的時(shí)間片輪轉(zhuǎn)法的時(shí)鐘控制,(詳見線程管理系統(tǒng)中的實(shí)現(xiàn)實(shí)例中,對(duì)線程調(diào)度的改進(jìn)部分)不一定每次時(shí)鐘中斷都會(huì)引起線程的切換,而是由該線程是否的時(shí)間片是否已經(jīng)用完來決定。分時(shí)系統(tǒng)線程優(yōu)先級(jí)的計(jì)算(詳見線程管理 XE 線程管理 系統(tǒng)中的實(shí)現(xiàn)實(shí)例中,對(duì)線程調(diào)度的改進(jìn)部分)線程進(jìn)入睡眠狀態(tài)時(shí)的時(shí)間計(jì)算可以通過時(shí)鐘中斷機(jī)制來實(shí)現(xiàn)sleep系統(tǒng)調(diào)用,在時(shí)鐘中斷處理程序中,每隔一定的時(shí)間對(duì)定時(shí)睡眠線程的時(shí)間進(jìn)行一次評(píng)估,判斷是否需要喚醒它們。Nachos利用其模擬的中斷機(jī)制來模擬時(shí)鐘中斷。時(shí)鐘中斷間隔由TimerTicks宏決定(100倍Tick的時(shí)間)。在系統(tǒng)模擬時(shí)有一個(gè)缺陷,如果系統(tǒng)就緒進(jìn)程不止一個(gè)的話,每

27、次時(shí)鐘中斷都一定會(huì)發(fā)生進(jìn)程的切換(見中TimerInterruptHandler函數(shù))。所以運(yùn)行Nachos時(shí),如果以同樣的方式提交進(jìn)程,系統(tǒng)的結(jié)果將是一樣的。這不符合操作系統(tǒng)的運(yùn)行不確定性的特性。所以在模擬時(shí)鐘中斷的時(shí)候,加入了一個(gè)隨機(jī)因子,如果該因子設(shè)置的話,時(shí)鐘中斷發(fā)生的時(shí)機(jī)將在一定范圍內(nèi)是隨機(jī)的。這樣有些用戶程序 XE 用戶程序 在同步方面的錯(cuò)誤就比較容易發(fā)現(xiàn)。但是這樣的時(shí)鐘中斷和真正操作系統(tǒng)中的時(shí)鐘中斷將有不同的含義。不能象真正的操作系統(tǒng)那樣通過時(shí)鐘中斷來計(jì)算時(shí)間等等。是否需要隨機(jī)時(shí)鐘中斷可以通過設(shè)置選項(xiàng)(-rs)來實(shí)現(xiàn)。Timer類 XE Timer類 的實(shí)現(xiàn)很簡(jiǎn)單,當(dāng)生成出一個(gè)T

28、imer類的實(shí)例時(shí),就設(shè)計(jì)了一個(gè)模擬的時(shí)鐘中斷。這里考慮的問題是:怎樣實(shí)現(xiàn)定期發(fā)生時(shí)鐘中斷?在Timer的初始化函數(shù)中,借用TimerHandler內(nèi)部函數(shù)(見第1行)。為什么不直接用初始化函數(shù)中的timerHandler參數(shù)作為中斷處理函數(shù)呢?因?yàn)槿绻苯邮褂胻imerHandler作為時(shí)鐘中斷處理函數(shù),第8行是將一個(gè)時(shí)鐘中斷插入等待處理中斷隊(duì)列,一旦中斷時(shí)刻到來,立即進(jìn)行中斷處理,處理結(jié)束后并沒有機(jī)會(huì)將下一個(gè)時(shí)鐘中斷插入到等待處理中斷隊(duì)列。TimerHandler內(nèi)部函數(shù)正是處理這個(gè)問題。當(dāng)時(shí)鐘中斷時(shí)刻到來時(shí),調(diào)用TimerHandler函數(shù),其調(diào)用TimerExpired方法,該方法將新

29、的時(shí)鐘中斷插入到等待處理中斷隊(duì)列中,然后再調(diào)用真正的時(shí)鐘中斷處理函數(shù)。這樣Nachos就可以定時(shí)的收到時(shí)鐘中斷。那么為什么不將TimerExpired方法作為時(shí)鐘中斷在Timer的初始化函數(shù)中調(diào)用呢?這是由于C+語言不能直接引用一個(gè)類內(nèi)部方法的指針,所以借用TimerHandler內(nèi)部函數(shù)。這也是TimerExpired必須設(shè)計(jì)成public的方法的原因,因?yàn)樗籘imerHandler調(diào)用。這樣的方法不僅僅在Timer模擬時(shí)鐘中斷中用到,所有需要定期發(fā)生的中斷都可以采用這樣的方法,如Nachos需要定期地檢查是否有終端的輸入、網(wǎng)絡(luò)是否有發(fā)給自己的報(bào)文 XE 報(bào)文 等都是用這種方式實(shí)現(xiàn)。詳見

30、 network.cc 以及。TimeOfextInterrupt()方法的作用是計(jì)算下一次時(shí)鐘中斷發(fā)生的時(shí)機(jī),如果需要時(shí)鐘中斷發(fā)生的時(shí)機(jī)是隨機(jī)的,可以在Nachos命令行中設(shè)置 rs 選項(xiàng)。這樣,Nachos的線程切換的時(shí)機(jī)將會(huì)是隨機(jī)的。但是此時(shí)時(shí)鐘中斷則不能作為系統(tǒng)計(jì)時(shí)的標(biāo)準(zhǔn)了。理解Nachos中線程運(yùn)行機(jī)制Nachos中的系統(tǒng)線程和用戶進(jìn)程宿主機(jī)CPU和寄存器虛擬機(jī)CPU和寄存器用戶程序系統(tǒng)線程用戶程序系統(tǒng)線程用戶進(jìn)程用戶程序系統(tǒng)線程系統(tǒng)線程系統(tǒng)線程系統(tǒng)線程N(yùn)achos為線程提供的功能函數(shù)有:生成一個(gè)線程(Fork)使線程睡眠等待(Sleep)結(jié)束線程(Finish)設(shè)置線程狀態(tài)(set

31、Status)放棄處理機(jī)(Yield)線程系統(tǒng)的結(jié)構(gòu)如圖所示:用戶進(jìn)程信號(hào)量條件變量鎖Thread類模擬中斷正文切換線程調(diào)度Nachos線程系統(tǒng)的結(jié)構(gòu)線程管理 XE 線程管理 系統(tǒng)中,有兩個(gè)與機(jī)器相關(guān)的函數(shù),正文切換過程依賴于具體的機(jī)器,這是因?yàn)橄到y(tǒng)線程切換是借助于宿主機(jī)的正文切換,正文切換過程中的寄存器保護(hù),建立初始調(diào)用框架等操作對(duì)不同的處理機(jī)結(jié)構(gòu)是不一樣的。其中一個(gè)函數(shù)是ThreadRoot,它是所有線程運(yùn)行的入口;另一個(gè)函數(shù)是SWITCH,它負(fù)責(zé)線程之間的切換。 Scheduler類用于實(shí)現(xiàn)線程的調(diào)度。它維護(hù)一個(gè)就緒線程隊(duì)列,當(dāng)一個(gè)線程可以占用處理機(jī)時(shí),就可以調(diào)用ReadyToRun方法

32、把這個(gè)線程放入就緒線程隊(duì)列,并把線程狀態(tài)改成就緒態(tài)。FindNextToRun方法根據(jù)調(diào)度策略,取出下一個(gè)應(yīng)運(yùn)行的線程,并把這個(gè)線程從就緒線程隊(duì)列中刪除。如果就緒線程隊(duì)列為空,則此函數(shù)返回空(NULL)?,F(xiàn)有的調(diào)度策略是先進(jìn)先出策略(FIFO),Thread類的對(duì)象既用作線程的控制塊,相當(dāng)于進(jìn)程管理中的PCB,作用是保存線程狀態(tài)、進(jìn)行一些統(tǒng)計(jì),又是用戶調(diào)用線程系統(tǒng)的界面。用戶生成一個(gè)新線程的方法是:Thread* newThread = new Thread(New Thread);/ 生成一個(gè)線程類newThread-Fork(ThreadFunc,ThreadFuncArg);/ 定義新線

33、程的執(zhí)行函數(shù)及其參數(shù) Fork方法分配一塊固定大小的內(nèi)存作為線程的堆棧,在棧頂放入ThreadRoot的地址。當(dāng)新線程被調(diào)上CPU時(shí),要用SWITCH函數(shù)切換線程圖像,SWITCH函數(shù)返回時(shí),會(huì)從棧頂取出返回地址,于是將ThreadRoot放在棧頂,在SWITCH結(jié)束后就會(huì)立即執(zhí)行ThreadRoot函數(shù)。ThreadRoot是所有線程的入口,它會(huì)調(diào)用Fork的兩個(gè)參數(shù),運(yùn)行用戶指定的函數(shù);Yield方法用于本線程放棄處理機(jī)。Sleep方法可以使當(dāng)前線程轉(zhuǎn)入阻塞態(tài),并放棄CPU,直到被另一個(gè)線程喚醒,把它放回就緒線程隊(duì)列。在沒有就緒線程時(shí),就把時(shí)鐘前進(jìn)到一個(gè)中斷發(fā)生的時(shí)刻,讓中斷發(fā)生并處理此中

34、斷,這是因?yàn)樵跊]有線程占用CPU時(shí),只有中斷處理程序可能喚醒一個(gè)線程,并把它放入就緒線程隊(duì)列。線程要等到本線程被喚醒后,并且又被線程調(diào)度模塊調(diào)上CPU時(shí),才會(huì)從Sleep函數(shù)返回。有趣的是,新取出的就緒線程有可能就是這個(gè)要睡眠的線程。例如,如果系統(tǒng)中只有一個(gè)A線程,A線程在讀磁盤的時(shí)候會(huì)進(jìn)入睡眠,等待磁盤操作完成。因?yàn)檫@時(shí)只有一個(gè)線程,所以A線程不會(huì)被調(diào)下CPU,只是在循環(huán)語句中等待中斷。當(dāng)磁盤操作完成時(shí),磁盤會(huì)發(fā)出一個(gè)磁盤讀操作中斷,此中斷將喚醒A線程,把它放入就緒隊(duì)列。這樣,當(dāng)A線程跳出循環(huán)時(shí),取出的就緒線程就是自己。這就要求線程的正文切換程序可以將一個(gè)線程切換到自己, Nachos的線程

35、正文切換程序SWITCH可以做到這一點(diǎn),于是A線程實(shí)際上并沒有被調(diào)下CPU,而是繼續(xù)運(yùn)行下去了。Nachos線程管理 XE 線程管理 系統(tǒng)的初步實(shí)現(xiàn)1. 工具模塊分析(文件)工具模塊定義了一些在Nachos設(shè)計(jì)中有關(guān)的工具函數(shù),和整個(gè)系統(tǒng)的設(shè)計(jì)沒有直接的聯(lián)系,所以這里僅作一個(gè)簡(jiǎn)單的介紹。List類在Nachos中廣泛使用,它定義了一個(gè)鏈表結(jié)構(gòu),有關(guān)List的數(shù)據(jù)結(jié)構(gòu)和實(shí)現(xiàn)如下所示:class ListElement /定義了List中的元素類型 public: ListElement(void *itemPtr, int sortKey);/初始化方法 ListElement *next;/指

36、向下一個(gè)元素的指針 int key; /對(duì)應(yīng)于優(yōu)先隊(duì)列的鍵值 void *item; /實(shí)際有效的元素指針;其中,實(shí)際有效元素指針是(void *)類型的,說明元素可以是任何類型。class List public:List();/初始化方法List();/析構(gòu)方法void Prepend(void *item);/將新元素增加在鏈?zhǔn)譾oid Append(void *item); /將新元素增加在鏈尾void *Remove(); /刪除鏈?zhǔn)自夭⒎祷卦撛豽oid Mapcar(VoidFunctionPtr func);/將函數(shù)func作用在鏈中每個(gè)元素上bool IsEmpty();/

37、判斷鏈表是否為空void SortedInsert(void *item, int sortKey);/將元素根據(jù)key值優(yōu)先權(quán)插入到鏈中void *SortedRemove(int *keyPtr); /將key值最小的元素從鏈中刪除,/并返回該元素 private: ListElement *first; /鏈表中的第一個(gè)元素 ListElement *last;/鏈表中的最后一個(gè)元素;其它的工具函數(shù)如min和max以及一些同調(diào)試有關(guān)的函數(shù),這里就不再贅述。2. 線程啟動(dòng)和調(diào)度模塊分析(文件)線程啟動(dòng)和線程調(diào)度是線程管理 XE 線程管理 的重點(diǎn)。在Nachos中,線程是最小的調(diào)度單位,在同

38、一時(shí)間內(nèi),可以有幾個(gè)線程處于就緒狀態(tài)。Nachos的線程切換借助于宿主機(jī)的正文切換,由于這部分內(nèi)容與機(jī)器密切相關(guān),而且直接同宿主機(jī)的寄存器進(jìn)行交道,所以這部分是用匯編來實(shí)現(xiàn)的。由于Nachos可以運(yùn)行在多種機(jī)器上,不同機(jī)器的寄存器數(shù)目和作用不一定相同,所以在中針對(duì)不同的機(jī)器進(jìn)行了不同的處理。讀者如果需要將Nachos移植到其它機(jī)器上,就需要修改這部分的內(nèi)容。2.1 ThreadRoot函數(shù)Nachos中,除了main線程外,所有其它線程都是從ThreadRoot入口運(yùn)行的。它的語法是:ThreadRoot (int InitialPC, int InitialArg, int WhenDone

39、PC, int StartupPC)其中,InitialPC指明新生成線程的入口函數(shù)地址,InitialArg是該入口函數(shù)的參數(shù);StartupPC是在運(yùn)行該線程是需要作的一些初始化工作,比如開中斷;而WhenDonePC是當(dāng)該線程運(yùn)行結(jié)束時(shí)需要作的一些后續(xù)工作。在Nachos的源代碼中,沒有任何一個(gè)函數(shù)和方法顯式地調(diào)用ThreadRoot函數(shù),ThreadRoot函數(shù)只有在線程切換時(shí)才被調(diào)用到。一個(gè)線程在其初始化的最后準(zhǔn)備工作中調(diào)用StackAllocate方法(見本章),該方法設(shè)置了幾個(gè)寄存器的值(InterruptEnable函數(shù)指針,ThreadFinish函數(shù)指針以及該線程需要運(yùn)行函

40、數(shù)的函數(shù)指針和運(yùn)行函數(shù)的參數(shù)) ,該線程第一次被切換上處理機(jī)運(yùn)行時(shí)調(diào)用的就是ThreadRoot函數(shù)。其工作過程是:調(diào)用 StartupPC 函數(shù);調(diào)用 InitialPC 函數(shù);調(diào)用 WhenDonePC 函數(shù);這里我們可以看到,由ThreadRoot入口可以轉(zhuǎn)而運(yùn)行線程所需要運(yùn)行的函數(shù),從而達(dá)到生成線程的目的。2.2 SWITCH函數(shù)Nachos中系統(tǒng)線程的切換是借助宿主機(jī)的正文切換。SWITCH函數(shù)就是完成線程切換的功能。SWITCH的語法是這樣的:void SWITCH (Thread *t1, Thread *t2);其中t1是原運(yùn)行線程指針,t2是需要切換到的線程指針。線程切換的三

41、步曲是:保存原運(yùn)行線程的狀態(tài)恢復(fù)新運(yùn)行線程的狀態(tài)在新運(yùn)行線程的棧空間上運(yùn)行新線程3. 線程模塊分析(文件)Thread類實(shí)現(xiàn)了操作系統(tǒng)的線程控制塊,同操作系統(tǒng)課程中進(jìn)程程管理中的PCB (Process Control Block) 有相似之處。Thread線程控制類較PCB為簡(jiǎn)單的多,它沒有線程標(biāo)識(shí) (pid)、實(shí)際用戶標(biāo)識(shí) (uid)等和線程操作不是非常有聯(lián)系的部分,也沒有將PCB分成proc結(jié)構(gòu)和user結(jié)構(gòu)。這是因?yàn)橐粋€(gè)Nachos線程是在宿主機(jī)上運(yùn)行的。無論是系統(tǒng)線程和用戶進(jìn)程,Thread線程控制類的實(shí)例都生成在宿主機(jī)而不是生成在虛擬機(jī)上。所以不存在實(shí)際操作系統(tǒng)中proc結(jié)構(gòu)常駐內(nèi)

42、存,而user結(jié)構(gòu)可以存放在盤交換區(qū)上的情況,將原有的兩個(gè)結(jié)構(gòu)合并是Nachos作的一種簡(jiǎn)化。Nachos對(duì)線程的另一個(gè)簡(jiǎn)化是每個(gè)線程棧段的大小是固定的,為4096-5個(gè)字 (word),而且是不能動(dòng)態(tài)擴(kuò)展的。所以Nachos中的系統(tǒng)線程中不能使用很大的棧空間,比如:void foo () int buff10000; .可能會(huì)不能正常執(zhí)行,如果需要使用很大空間,可以在Nachos的運(yùn)行堆中申請(qǐng):void foo () int *buf = new int10000; .如果系統(tǒng)線程需要使用的??臻g大于規(guī)定棧空間的大小,可以修改StackSize宏定義。Thread類的定義和實(shí)現(xiàn)如下所示:cl

43、ass Thread private:int* stackTop; /當(dāng)前堆棧指針int machineStateMachineStateSize; /宿主機(jī)的運(yùn)行寄存器 public:Thread(char* debugName);/初始化線程Thread(); /析構(gòu)方法void Fork(VoidFunctionPtr func, int arg); /生成一個(gè)新線程,執(zhí)行func(arg)void Yield(); /切換到其它線程運(yùn)行void Sleep(); /線程進(jìn)入睡眠狀態(tài)void Finish(); /線程結(jié)束時(shí)調(diào)用void CheckOverflow(); /測(cè)試線程棧段是

44、否溢出void setStatus(ThreadStatus st);/設(shè)置線程狀態(tài)char* getName() return (name); /取得線程名(調(diào)試用)void Print() printf(%s, , name); /打印當(dāng)前線程名(調(diào)試用) private:int* stack;/線程的棧底指針ThreadStatus status;/當(dāng)前線程狀態(tài)char* name;/線程名(調(diào)試用)void StackAllocate(VoidFunctionPtr func, int arg);/申請(qǐng)線程的棧空間#ifdef USER_PROGRAMint userRegisters

45、NumTotalRegs;/虛擬機(jī)的寄存器組 public:void SaveUserState();/線程切換時(shí)保存虛擬機(jī)寄存器void RestoreUserState();/線程切換時(shí)恢復(fù)虛擬機(jī)寄存器組AddrSpace *space;/線程運(yùn)行的用戶程序 XE 用戶程序 #endif線程狀態(tài)有四種,狀態(tài)之間的轉(zhuǎn)換如圖3.6所示:Nachos線程的狀態(tài)轉(zhuǎn)換運(yùn)行結(jié)束等待的事件發(fā)生等待某事件發(fā)生初始化結(jié)束處理機(jī)調(diào)度運(yùn)行被迫放棄處理機(jī)運(yùn)行態(tài)阻塞態(tài)初啟態(tài)就緒態(tài)初啟態(tài)用戶進(jìn)程在線程切換的時(shí)候,除了需要保存宿主機(jī)的狀態(tài)外,必須還要保存虛擬機(jī)的寄存器狀態(tài)。UserRegisters數(shù)組變量和SaveU

46、serState(), RestoreUserState()方法就是為了用戶進(jìn)程的切換設(shè)計(jì)的。Fork 方法 語法:void Fork (VoidFunctionPtr func, int arg) 參數(shù):func:新線程運(yùn)行的函數(shù)arg:func函數(shù)的參數(shù) 功能:線程初始化之后將線程設(shè)置成可運(yùn)行的。 實(shí)現(xiàn):申請(qǐng)線程棧空間初始化該??臻g,使其滿足SWITCH函數(shù)進(jìn)行線程切換的條件將該線程放到就緒隊(duì)列中。 返回:空StackAllocate 方法 語法:void StackAllocate (VoidFunctionPtr func, int arg) 參數(shù):func:新線程運(yùn)行的函數(shù)arg:f

47、unc函數(shù)的參數(shù) 功能:為一個(gè)新線程申請(qǐng)??臻g,并設(shè)置好準(zhǔn)備運(yùn)行線程的條件。 實(shí)現(xiàn):void Thread:StackAllocate (VoidFunctionPtr func, int arg)stack = (int *) AllocBoundedArray(StackSize * sizeof(int);/申請(qǐng)線程的??臻gstackTop = stack + StackSize - 4;/設(shè)置棧首指針*(-stackTop) = (int)ThreadRoot;/線程準(zhǔn)備好運(yùn)行后進(jìn)行線程切換,會(huì)切換到ThreadRoot函數(shù)。ThreadRoot函數(shù)/將會(huì)開中斷,并調(diào)用func(arg

48、)成為一個(gè)獨(dú)立的調(diào)度單位。*stack = STACK_FENCEPOST;/設(shè)置棧溢出標(biāo)志 machineStatePCState = (int) ThreadRoot;/設(shè)置PC指針,從ThreadRoot開始運(yùn)行 machineStateStartupPCState = (int) InterruptEnable; machineStateInitialPCState = (int) func; machineStateInitialArgState = arg; machineStateWhenDonePCState = (int) ThreadFinish;/以上是為ThreadRo

49、ot作好準(zhǔn)備,ThreadRoot將分別調(diào)用InterruptEnable,/func(arg)和ThreadFinish。 返回:空4. 線程調(diào)度算法模塊分析(文件)該模塊的作用是進(jìn)行線程的調(diào)度。在Nachos系統(tǒng)中,有一個(gè)線程就緒隊(duì)列,其中是所有就緒線程。調(diào)度算法非常簡(jiǎn)單,就是取出第一個(gè)放在處理機(jī)運(yùn)行即可。由于Nachos中線程沒有優(yōu)先級(jí),所以線程就緒隊(duì)列是沒有優(yōu)先級(jí)的。讀者可以在這一點(diǎn)上進(jìn)行加強(qiáng),實(shí)現(xiàn)有優(yōu)先級(jí)的線程調(diào)度。4.1 Run方法語法:void Run (Thread *nextThread)參數(shù):nextThread:需要切換運(yùn)行的線程功能:當(dāng)前運(yùn)行強(qiáng)制切換到nextThrea

50、d就緒線程運(yùn)行實(shí)現(xiàn):如果是用戶線程,保存當(dāng)前虛擬機(jī)的狀態(tài)檢查當(dāng)前運(yùn)行線程棧段是否溢出。(由于不是每時(shí)每刻都檢查棧段是否溢出,所以這時(shí)候線程的運(yùn)行可能已經(jīng)出錯(cuò))將nextThread的狀態(tài)設(shè)置成運(yùn)行態(tài),并作為currentThread現(xiàn)運(yùn)行線程(在調(diào)用Run方法之前,當(dāng)前運(yùn)行線程已經(jīng)放入就緒隊(duì)列中,變成就緒態(tài))(以上是運(yùn)行在現(xiàn)有的線程??臻g上,以下是運(yùn)行在nextThread的??臻g上)切換到nextThread線程運(yùn)行釋放threadToBeDestroyed線程需要??臻g(如果有的話)如果是用戶線程,恢復(fù)當(dāng)前虛擬機(jī)的狀態(tài) 返回:空5.Nachos主控模塊分析(文件)該模塊是整個(gè)Nachos系

51、統(tǒng)的入口,它分析了Nachos的命令行參數(shù),根據(jù)不同的選項(xiàng)進(jìn)行不同功能的初始化設(shè)置。選項(xiàng)的設(shè)置如下所示:一般選項(xiàng):-d:顯示特定的調(diào)試信息-rs:使得線程可以隨機(jī)切換-z:打印版權(quán)信息和用戶進(jìn)程有關(guān)的選項(xiàng):-s:使用戶進(jìn)程進(jìn)入單步調(diào)試模式-x:執(zhí)行一個(gè)用戶程序 XE 用戶程序 -c:測(cè)試終端輸入輸出和文件系統(tǒng)有關(guān)的選項(xiàng):-f:格式化模擬磁盤-cp:將一個(gè)文件從宿主機(jī)拷貝到Nachos模擬磁盤上-p:將Nachos磁盤上的文件顯示出來-r:將一個(gè)文件從Nachos模擬磁盤上刪除-l:列出Nachos模擬磁盤上的文件-D:打印出Nachos文件系統(tǒng)的內(nèi)容-t:測(cè)試Nachos文件系統(tǒng)的效率和網(wǎng)絡(luò)有

52、關(guān)的選項(xiàng):-n:設(shè)置網(wǎng)絡(luò)的可靠度(在0-1之間的一個(gè)小數(shù))-m:設(shè)置自己的HostID-o:執(zhí)行網(wǎng)絡(luò)測(cè)試程序6. 同步機(jī)制模塊分析(文件)線程的同步和互斥是多個(gè)線程協(xié)同工作的基礎(chǔ)。Nachos提供了三種同步和互斥的手段:信號(hào)量、鎖機(jī)制以及條件變量機(jī)制,提供三種同步互斥機(jī)制是為了用戶使用方便。在同步互斥機(jī)制的實(shí)現(xiàn)中,很多操作都是原子操作。Nachos是運(yùn)行在單一處理器上的操作系統(tǒng),在單一處理器上,實(shí)現(xiàn)原子操作只要在操作之前關(guān)中斷即可,操作結(jié)束后恢復(fù)原來中斷狀態(tài)。6.1 信號(hào)量 ( Semaphore )Nachos已經(jīng)實(shí)現(xiàn)了Semaphore,它的基本結(jié)構(gòu)如下所示:class Semaphore

53、 public:void P(); /信號(hào)量的P操作void V(); /信號(hào)量的V操作 private:int value; /信號(hào)量值 ( =0)List *queue; /線程等待隊(duì)列;信號(hào)量的私有屬性有信號(hào)量的值,它是一個(gè)閥門。線程等待隊(duì)列中存放所有等待該信號(hào)量的線程。信號(hào)量有兩個(gè)操作:P操作和V操作,這兩個(gè)操作都是原子操作。6.1.1 P操作當(dāng)value等于0時(shí),將當(dāng)前運(yùn)行線程放入線程等待隊(duì)列。當(dāng)前運(yùn)行線程進(jìn)入睡眠狀態(tài),并切換到其它線程運(yùn)行。當(dāng)value大于0時(shí),value-。 V操作如果線程等待隊(duì)列中有等待該信號(hào)量的線程,取出其中一個(gè)將其設(shè)置成就緒態(tài),準(zhǔn)備運(yùn)行。value+;6.2

54、 鎖機(jī)制鎖機(jī)制是線程進(jìn)入臨界區(qū)的工具。一個(gè)鎖有兩種狀態(tài),BUSY和FREE。當(dāng)鎖處于FREE態(tài)時(shí),線程可以取得該鎖后進(jìn)入臨界區(qū),執(zhí)行完臨界區(qū)操作之后,釋放鎖;當(dāng)鎖處于BUSY態(tài)時(shí),需要申請(qǐng)?jiān)撴i的線程進(jìn)入睡眠狀態(tài),等到鎖為FREE態(tài)時(shí),再取得該鎖。鎖的基本結(jié)構(gòu)如下所示:class Lock public:Lock(char* debugName); /初始化方法Lock();/析構(gòu)方法char* getName() return name; /取出鎖名(調(diào)試用)void Acquire(); /獲得鎖方法void Release(); /釋放鎖方法bool isHeldByCurrentThre

55、ad();/判斷鎖是否為現(xiàn)運(yùn)行線程擁有 private:char* name;/鎖名(調(diào)試用);在現(xiàn)有的Nachos中,沒有給出鎖機(jī)制的實(shí)現(xiàn),鎖的基本結(jié)構(gòu)也只給出了部分內(nèi)容,其它內(nèi)容可以視實(shí)現(xiàn)決定。總體來說,鎖有兩個(gè)操作Acquire和Release,它們都是原子操作。6.3條件變量條件變量和信號(hào)量與鎖機(jī)制不一樣,它是沒有值的。(實(shí)際上,鎖機(jī)制是一個(gè)二值信號(hào)量,可以通過信號(hào)量來實(shí)現(xiàn))當(dāng)一個(gè)線程需要的某種條件沒有得到滿足時(shí),可以將自己作為一個(gè)等待條件變量的線程插入所有等待該條件變量的隊(duì)列;只要條件一旦滿足,該線程就會(huì)被喚醒繼續(xù)運(yùn)行。條件變量總是和鎖機(jī)制一同使用,它的基本結(jié)構(gòu)如下:class Co

56、ndition public:Condition(char* debugName);/初始化方法Condition();/析構(gòu)方法char* getName() return (name); /取出條件變量名(調(diào)試用)void Wait(Lock *conditionLock); /線程進(jìn)入等待 void Signal(Lock *conditionLock); /喚醒一個(gè)等待該條件變量線程void Broadcast(Lock *conditionLock);/喚醒等待該條件變量的線程 private: char* name;/條件變量名(調(diào)試用);在現(xiàn)有的Nachos中,沒有給出條件變量的

57、實(shí)現(xiàn),條件變量的基本結(jié)構(gòu)也只給出了部分內(nèi)容,其它內(nèi)容可以視實(shí)現(xiàn)決定??傮w來說,條件變量有三個(gè)操作Wait、Signal以及BroadCast,所有的這些操作必須在當(dāng)前線程獲得一個(gè)鎖的前提下,而且所有對(duì)一個(gè)條件變量進(jìn)行的操作必須建立在同一個(gè)鎖的前提下。理解Nachos中支持用戶進(jìn)程的機(jī)制Nachos 對(duì)內(nèi)存、寄存器以及CPU的模擬Nachos機(jī)器模擬很重要的部分是內(nèi)存和寄存器的模擬。Nachos寄存器組模擬了全部32個(gè)MIPS XE MIPS 機(jī)(R2/3000 XE R2/3000 )的寄存器,同時(shí)加上有關(guān)Nachos系統(tǒng)調(diào)試用的8個(gè)寄存器,以期讓模擬更加真實(shí)化并易于調(diào)試,對(duì)于一些特殊的寄存器

58、說明如下:寄存器名編號(hào)描述StackReg29用戶程序 XE 用戶程序 的堆棧指針RetAddrReg31存放過程調(diào)用的返回地址HiReg32存放乘法結(jié)果的高32位LoReg33存放乘法結(jié)果的低32位PCReg34當(dāng)前PC指針NextPCReg35下一條執(zhí)行語句的PC指針PrevPCReg36上一條執(zhí)行語句的PC指針(調(diào)試用)LoadReg37需要延遲載入的寄存器編號(hào)LoadValueReg38需要延遲載入的寄存器值BadAddReg39當(dāng)出錯(cuò)陷入(Exception)時(shí)用戶程序 XE 用戶程序 的邏輯地址Nachos用宿主機(jī)的一塊內(nèi)存模擬自己的內(nèi)存。為了簡(jiǎn)便起見,每個(gè)內(nèi)存頁的大小同磁盤扇區(qū)的

59、大小相同,而整個(gè)內(nèi)存的大小遠(yuǎn)遠(yuǎn)小于模擬磁盤的大小。由于Nachos是一個(gè)教學(xué)操作系統(tǒng),在內(nèi)存分配上和實(shí)際的操作系統(tǒng)是有區(qū)別的。事實(shí)上,Nachos的內(nèi)存只有當(dāng)需要執(zhí)行用戶程序 XE 用戶程序 時(shí)用戶程序的一個(gè)暫存地,而作為操作系統(tǒng)內(nèi)部使用的數(shù)據(jù)結(jié)構(gòu)不存放在Nachos的模擬內(nèi)存中,而是申請(qǐng)Nachos所在宿主機(jī)的內(nèi)存。所以Nachos的一些重要的數(shù)據(jù)結(jié)構(gòu)如線程控制結(jié)構(gòu)等的數(shù)目可以是無限的,不受Nachos模擬內(nèi)存大小的限制。這里需要強(qiáng)調(diào)的是,此處Nachos模擬的寄存器組同Thread類(第三章第三節(jié))中的machineState數(shù)組表示的寄存器組不同,后者代表的是宿主機(jī)的寄存器組,是實(shí)際存在

60、的;而前者只是為了運(yùn)行擁護(hù)程序模擬的。在用戶程序 XE 用戶程序 運(yùn)行過程中,會(huì)有很多系統(tǒng)陷入核心的情況。系統(tǒng)陷入有兩大類原因:進(jìn)行系統(tǒng)調(diào)用陷入和系統(tǒng)出錯(cuò)陷入。系統(tǒng)調(diào)用陷入在用戶程序進(jìn)行系統(tǒng)調(diào)用時(shí)發(fā)生。系統(tǒng)調(diào)用可以看作是軟件指令,它們有效地彌補(bǔ)了機(jī)器硬件指令不足;系統(tǒng)出錯(cuò)陷入在系統(tǒng)發(fā)生錯(cuò)誤時(shí)發(fā)生,比如用戶程序使用了非法指令以及用戶程序邏輯地址同實(shí)際的物理地址映射出錯(cuò)等情況。不同的出錯(cuò)陷入會(huì)有不同的處理,比如用戶程序邏輯地址映射出錯(cuò)會(huì)引起頁面的重新調(diào)入,而用戶程序使用了非法指令則需要向用戶報(bào)告等等。Nachos處理的陷入有:需要注意的是,雖然這里的很多方法和屬性規(guī)定為public的,但是它們只能

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論