1. 程式人生 > >《現代作業系統(中文第三版)》課後習題——第二章 程序與執行緒

《現代作業系統(中文第三版)》課後習題——第二章 程序與執行緒

第二章 程序和執行緒

1、圖2-2中給出了三個程序狀態,在理論上,三個狀態可以有六種轉換,每個狀態兩個。但是,圖中只給出了四種轉換。有沒有可能發生其他兩種轉換中的一個或兩個?

答:從阻塞到執行的轉換是可以想象的。假設某個程序在I/O上阻塞,而且I/O結束,如果此時CPU空閒,該程序就可以從阻塞態直接轉到執行態。而另外一種轉換(從阻塞態到就緒態)是不可能的。一個就緒程序是不可能做任何會產生阻塞的I/O或者別的什麼事情。只有執行的程序才能被阻塞。

2、假設要設計一種先進的計算機體系結構,它使用硬體而不是中斷來完成程序切換。CPU需要哪些資訊?請描述用硬體完成程序切換的工作過程。

答:應該有一個暫存器包含當前程序表項的指標。當I/O結束時,CPU將把當前的機器狀態存入到當前程序表項中。然後,將轉到中斷裝置的中斷向量,讀取另一個過程表項的指標(服務例程),然後,就可以啟動這個程序了。

3、在所有當代計算機中,至少有部分中斷處理程式是用匯編語言編寫的。為什麼?

答:通常,高階語言不允許訪問CPU硬體,而這種訪問是必需的。例如,中斷處理程式可能需要禁用和啟用某個特定裝置的中斷服務,或者處理程序堆疊區的資料。另外,中斷服務例程需要儘快地執行。

4、當中斷或系統呼叫把控制轉給作業系統時,通常將核心堆疊和被中斷程序的執行堆疊分離。為什麼?

答:核心使用單獨的堆疊有若干的原因。其中兩個原因如下:

首先,不希望作業系統崩潰,由於某些使用者程式不允許足夠的堆疊空間。

第二,如果核心將資料保留在使用者空間,然後從系統呼叫返回,那麼惡意的使用者可能使用這些資料找出某些關於其它程序的資訊。

5、多個作業能夠並行執行,比它們順序執行完成的要快。假設有兩個作業同時開始執行,每個需要10分鐘的CPU時間。如果順序執行,那麼最後一個作業需要多長時間可以完成?如果並行執行又需要多長時間?假設I/O等待佔50%。

答:CPU利用率計算公式:CPU利用率 = 1 - pn。設執行作業所需要的時間為T。

順序執行:T = (10 + 10) / 0.5 = 40(分鐘);

並行執行:p = 0.5,n = 2,CPU利用率 = 1 - 0.52 = 0.75,則T = (10 + 10) / 0.75 = 26.7(分鐘)。

6、在本章中說明的圖2-11a的模式不適合用於使用記憶體快取記憶體的檔案伺服器。為什麼不適合?每個程序可以有自己的快取記憶體嗎?

答:即使是有可能實現,也是很難保持檔案系統的一致性。假設某個客戶程序給伺服器程序1傳送請求要更新檔案。該程序更新其記憶體的cache項。然後,另一個客戶程序給伺服器程序2傳送請求讀取該檔案。不幸的是,如果該檔案還在 cache中,伺服器程序2對此毫不知情,將返回過時的資料。如果第一個程序在緩衝後將檔案寫到磁碟中, 而伺服器程序2每次讀取時檢查磁碟其快取的備份是否是最新的,系統還可以工作,但是需要避免磁碟訪問的所有快取系統。

7、如果建立一個多執行緒程序,若子程序得到全部父程序執行緒的副本,會出現問題。假如原有執行緒之一正在等待鍵盤輸入,現在則成為兩個執行緒在等待鍵盤輸入,每個程序有一個。在單執行緒程序中也會發生這種問題嗎?

答:不會。如果單執行緒程序在鍵盤上阻塞,就不能建立子程序。

8、在圖2-8中,給出了一個多執行緒Web伺服器。如果讀取檔案的惟一途徑是正常的阻塞read系統呼叫,那麼Web伺服器應該使用使用者級執行緒還是核心級執行緒?為什麼?

答:當工作者執行緒從磁碟讀取Web頁時,它就會被阻塞。如果使用使用者級執行緒,該動作將阻塞整個程序,而破壞多執行緒的價值。這就是使用核心執行緒的原因:某些執行緒的阻塞不會影響到其他執行緒。

9、在本章中,我們介紹了多執行緒Web伺服器,說明它比單執行緒伺服器和有限狀態機伺服器更好的原因。存在單執行緒伺服器更好一些的情形嗎?請給出一個例子。

答:是的。如果伺服器是完全CPU繫結的,則不需要多執行緒。這隻會增加不必要的複雜性。假設某個百萬人口區域的電話查號系統(類似於114),如果每個(姓名,電話號碼)記錄為64個字元,整個的資料庫則為64MB,這就很容易全部讀入伺服器記憶體中以提供快速的查詢。

10、在圖2-12中暫存器集合按每個執行緒中的內容列出而不是按每個程序中的內容列出。為什麼?畢竟機器只有一套暫存器。

答:當一個執行緒停止時,它在暫存器中有值。它們必須被儲存,就像程序停止時,必須儲存暫存器。多執行緒和多程序沒有什麼不同,所以每個執行緒需要自己的暫存器儲存區。

11、為什麼執行緒要通過呼叫thread_yield自願放棄CPU? 畢竟,由乾沒有周期性的時鐘中斷,執行緒可以不交回CPU。

答:程序中的執行緒合作。它們彼此不敵對。如果應用程式需要阻塞以執行得更好,那麼一個執行緒可以呼叫thread_yield自願放棄CPU。畢竟,同一個程序中的執行緒的全部程式碼通常是一個程式設計師寫的。

12、執行緒可以被時鐘中斷搶佔嗎?如果可以,什麼情形下可以?如果不可以,為什麼不可以?

答:使用者級執行緒不能被時鐘剝奪,除非整個程序的時間片用完。核心級執行緒可以單獨地被剝奪。在後一種情況下,如果執行緒執行過久,時鐘將中斷該當前程序,因而當前執行緒也被中斷。核心可以自由地從同一個程序中選取其他執行緒執行。

13、在本習題中,要求對使用單執行緒檔案伺服器和多執行緒檔案伺服器讀取檔案進行比較。假設所需要的資料都在塊快取記憶體中,花費15ms獲得工作請求,分派工作,並處理其餘必要工作。如果在三分之一時間時,需要一個磁碟操作,要另外花費75ms,此時該執行緒進入睡眠。在單執行緒情形下伺服器每秒鐘可以處理多少個請求?如果是多執行緒呢?

答:在單執行緒情況下,cache命中需15ms,cache未命中需要90ms。其加權平均為2/3*15+1/3*90。因此,平均請求為40ms,而伺服器每秒可處理25個。對於多執行緒伺服器,所有磁碟等待都是重疊的,因此每個請求都耗時15ms,而伺服器每秒可處理66.6666個請求。

14、在使用者空間實現執行緒,其最大的優點是什麼?最大的缺點是什麼?

答:最大的優勢就是效率。不需要陷入核心來切換執行緒。最大的缺點是,如果一個執行緒阻塞,整個程序都會阻塞。

15、在圖2-15中建立執行緒和執行緒列印訊息是隨機交織在一起的。有沒有方法可以嚴格按照以下次序執行:建立執行緒1,執行緒1列印訊息,執行緒1結束,建立執行緒2,執行緒2列印訊息,執行緒2結束,以此類推;如果有,是什麼方法,如果沒有請解釋原因。

答:是的,這是可以做到的。每次執行pthread_create後,主程式可以呼叫pthread_join等待剛剛建立的執行緒退出後再建立下一個執行緒。

16、在討論執行緒中的全域性變數時,曾使用過程create_global將儲存分配給指向變數的指標,而不是變數自身。這是必需的,還是由於該過程也需要使用這些值?

答:指標是確實必要的,因為全域性變數的大小是未知的。它可能是從字元到浮點數陣列的任何型別。如果儲存其值,就不得不把其大小傳遞給create_global,這都沒有問題,但是必須將其型別作為set_global的第二個引數,那麼read_global返回值的型別是什麼呢。

17、考慮執行緒全部在使用者空間實現的一個系統,其中執行時系統每秒鐘得到一個時鐘中斷。假設在該執行時系統中,當某個執行緒正在執行時發生一個時鐘中斷,此時會出現什麼問題?你有什麼解決該問題的建議嗎?

答:runtime系統可以正好在這一時刻阻塞或者解除阻塞某個執行緒,並且忙於處理排程佇列。此時並不適合於時鐘中斷處理程式開始檢查該佇列是否應該進行執行緒切換,因為它們可能處於不一致的狀態。解決方法可以是:當進入runtime系統後,設定一個標誌。時鐘處理程式將看到該標誌,並且設定其自己的標誌,然後返回。當runtime系統完成時,它將檢測時鐘標誌,看是否有時鐘中斷髮生,並且現在執行時鐘處理程式。

18、假設一個作業系統中不存在類似於select的系統呼叫來提前瞭解在從檔案、管道或裝置中讀取時是否安全,不過該作業系統確實允許設定報警時鐘,以便中斷阻塞的系統呼叫。在上述條件下,是否有可能在使用者空間中實現一個執行緒包?請加以討論。

答:這是可能的,不過效率很低。執行緒想要做一個系統呼叫,首先設定警報定時器,然後才執行呼叫。如果執行緒阻塞,定時器將控制歸還給執行緒包。當然,大多數呼叫是不阻塞的,而定時器必須被清除。每個可能被阻塞的系統呼叫都必須作為3個系統呼叫來執行。如果定時器過早失效,各種問題都可能發生。用這種方法建立執行緒包並不好。

19、在2.3.4節中所討論的優先順序反轉問題是否可能在使用者級執行緒中發生?為什麼?

答:當低優先順序程序位於其臨界區,而高優先順序程序就緒並且被排程時,將發生優先順序倒置問題。如果使用忙等待,高優先順序程序將一直執行。對於使用者級執行緒,不可能發生低優先順序執行緒突然被剝奪而允許高優先順序執行緒執行,因為是不可剝奪的。而核心級執行緒,就會出現這個問題。

20、在2.3.4節中,描述了一種有高優先順序程序H和低優先順序程序L的情況,導致了H陷入死迴圈。若採用輪轉排程演算法而不是優先順序排程演算法,還會發生這樣問題嗎?請給予討論。

答:在輪轉排程演算法下。L遲早會執行,最終它將會離開臨界區。關鍵是,在優先順序排程演算法下,L永遠不會執行;迴圈,它定期得到一個正常的時間片,所以有機會離開其臨界區。

21、在使用執行緒的系統中,若使用使用者級執行緒,是每個執行緒一個堆疊還是每個程序一個堆疊?如果使用核心級執行緒倩況又如何呢?請給予解釋。

答:每個執行緒都是自己呼叫例程,因此它必須有其自己的堆疊以儲存區域性變數、返回地址等等。這一點使用者級執行緒和核心級執行緒是一樣的。

22、在開發計算機時,通常首先用一個程式模擬,一次執行一條指令,甚至多處理器也嚴格按此模擬。在類似於這種沒有同時事件發生的情形下,會出現競爭條件嗎?

答:是的。模擬計算機也可以是多道程式設計的。例如,在程序A執行時,它讀取一些共享變數。然後發生了一個模擬時鐘週期和程序B執行。它也讀取相同的變數,然後對變數進行了加1操作。當程序A執行時,如果它也對變數進行了加1操作,就發生了競爭條件。

23、兩個程序在一個共享儲存器多處理器(即兩個CPU)上執行,當它們要共享一個公共記憶體時,圖2-23所示的採用變數turn的忙等待解決方案還有效嗎?

答:是,它還是有用的。當然,它依然是忙等待。

24、在程序排程是搶佔式的情形下,圖2-24中展示的互斥問題的Peterson解法能正常工作嗎?如果是非搶佔式的情況呢?

答:該方法對可剝奪排程完全沒問題。事實上,它就是為這種情況設計的。當排程為不可剝奪的,該方法將會失敗。假設初值為0,而程序1首先執行。它將一直迴圈,永不釋放CPU。

25、給出一個可以遮蔽中斷的作業系統如何實現訊號量的框架。

答:執行訊號量操作,作業系統首先要禁用中斷。然後,它讀取訊號量的值。如果執行down操作,而訊號量等於0,就將呼叫程序放入與訊號量有關的阻塞程序列表中。如果執行up操作,必須檢測看是否有任何程序在訊號量上被阻塞。如果有一個或多個程序被阻塞,從阻塞程序的列表中移出一個,使之就緒。當所有這些操作都完成後,就可以開啟中斷了。

26、請說明計數訊號量(即可以保持一個任意值的訊號量)如何僅通過二元訊號量和普通機器指令實現。

答:將每個計數訊號量與2個二值訊號量聯合:M用於互斥;S用於阻塞。另外,每個計數訊號量都組合一個用於儲存up次數減去down次數的計數器,以及在該訊號量上阻塞的程序列表。為了實現down操作,程序首先通過對M執行down操作,以獲得對訊號量、計數器以及列表的獨佔訪問權。然後,將計數器減 1。如果大於等於0, 只需對M執行up操作並退出即可。如果M為負數,就將該程序放入阻塞程序列表中。接著,對M執行up操作,對S執行down操作來阻塞該程序。為了實現up操作,首先對M執行down操作以獲得互斥,然後將計數器加1。如果計數器大於0, 則沒有程序阻塞,就只需對M執行up操作。不過, 如果計數器小於等於0, 則必須從列表中移出某些程序。最後,按次序對B和M執行up操作。

27、如果一個系統只有兩個程序,可以使用一個屏障來同步這兩個程序嗎?為什麼?

答:如果程式操作按階段執行,直到兩個程序都完成當前階段才能進入下一階段,這時就應該使用屏障。

28、如果執行緒在核心中實現,可以使用核心訊號量對同一個程序中的兩個執行緒進行同步嗎?如果執行緒在使用者空間實現呢?假設在其他程序中沒有執行緒必須訪問該訊號量。請討論你的答案。

答:對於核心執行緒,執行緒可以在訊號量上阻塞,而核心可以執行該程序中的其它執行緒。因而,使用訊號量沒有問題。而對於使用者級執行緒,當某個執行緒在訊號量上阻塞時,核心將認為整個程序都被阻塞,而且不再執行它。因此,程序失敗。

29、管程內的同步機制使用條件變數和兩個特殊操作wait和signal,一種更通用的同步形式是隻用一條原語waituntil,它以任意的布林謂詞作為引數。例如

waituntilx < 0 or y + z < n

這樣就不再需要signal原語。很顯然這一方式比Hoare或Brinch Hansen方案更通用,但它從未被採用過。為什麼?提示:請考慮其實現。

答:其實現的代價很高。 每次在某些等待變化的程序的謂詞中出現的任何變數, runtime系統都必須重新計算該謂詞,以判斷該程序是否能夠被解鎖。而對於 Hoare和Brinch Hansen管程,則只需signal原語即可喚醒程序。

30、一個快餐店有四類僱員:(1) 領班,接收頓客點的選單;(2)廚師,準備飯菜;(3)打包工,將飯菜裝在袋子裡;(4) 收銀員,將食品袋交給顧客並收錢。每個僱員可被看作一個進行通訊的順序程序。它們採用的程序間通訊方式是什麼?請將這個模型與UNIX中程序聯絡起來。

答:僱員之間通過訊息傳遞進行通訊:在該例中,訊息為訂單、食物和袋子。在UNIX中,該4個程序通過管道連線。

31、假設有一個使用信箱的訊息傳遞系統,當向滿信箱發訊息或從空信箱收訊息時,程序都不會阻塞,相反,會得到一個錯誤程式碼。程序響應錯誤程式碼的處理方式為一遍一遍地重試,直到成功為止。這種方式會導致競爭條件嗎?

答:它不會導致競爭條件(不會丟失任何東西),不過它是完全的忙等待。

32、CDC 6600計算機使用一種稱作處理器共享的有趣的輪轉排程演算法,它可以同時處理多達10個I/O程序。每條指令結束後都進行程序切換,這樣程序1執行指令1,程序2執行指令2,以此類推。程序切換由特殊硬體完成,所以沒有開銷。如果在沒有競爭的條件下一個程序需要T秒鐘完成,那麼當有n個程序共享處理器時完成一個程序需要多長時間?

答:它需要nT sec。

33、是否可以通過分析原始碼來確定程序是CPU密集型的還是I/O密集型的?如何能在執行時刻進行此項決定?

答:在簡單的情況下是有可能通過看原始碼來判斷是否為 I/O 繫結的。例如,程式開始時,將其所有輸入檔案讀入到緩衝器中,這種程式通常不是 I/O 繫結的;但是,對不同檔案進行增量地讀寫(諸如編譯程式)的問題很有可能是I/O繫結的。如果作業系統提供諸如 UNIX ps的命令,就可以得知被程式使用的CPU 時間的量,你能把這個時間量與整個的時間比較以判斷。當然,最有意義就是你是系統中唯一的使用者。

34、在“何時排程”一節中曾提到,有時一個重要程序可以在選擇下一個被阻塞程序進入執行的過程中發揮作用,從而改善排程效能。請給出可以這樣做的情形並解釋如何做。

答:對於管道中的多個程序,普通的父程序可以將資料流的資訊傳遞給作業系統。有了這個資訊,OS就可以確定哪個程序可以向需要輸入的阻塞程序提供輸出。

35、對某系統進行監測後表明,當阻塞在I/O之前時,平均每個程序執行時間為T。一次程序切換需要的時間為S,這裡S實際上就是開銷。對於採用時間片長度為Q的輪轉排程,請給出以下各種情況中CPU利用率的計算公式:

a) Q = ∞

b) Q > T

c) S < Q <T

d) Q = S

e) Q趨近於0

答:CPU的效率就是有用的CPU時間除以整個的CPU時間。當Q > T時,基本的週期就是程序執行T,然後程序切換S。因此,(a)和(b)的效率都是T/(T+S)。當時間片比T短時,每執行一次T就要求T/Q次程序切換,浪費時間為ST/Q。因此,其效率為

T/(T+ST/Q)

也就是下降到 Q/(Q+S),這就是(c)的答案。至於(d),只需以S替代Q,就可以計算出其效率為50%。最後,(e)的效率趨近於0。

36、有5個待執行作業,估計它們的執行時N分別是9, 6, 3, 5和X。採用哪種次序執行這些作業將得到最短的平均響應時間?(答案將依賴於X。)

答:最短作業優先可以使得平均響應時間最短。

0 < X ≤ 3: X, 3, 5, 6, 9.

3 < X ≤ 5: 3, X, 5, 6, 9.

5 < X ≤ 6: 3, 5, X, 6, 9.

6 < X ≤ 9: 3, 5, 6, X, 9.

X > 9: 3, 5,6, 9, X.

37、有5個批處理作業A到E,它們幾乎同時到達一個計算中心。估計它們的執行時間分別為10,6,2,4和8分鐘。其優先順序(由外部設定)分別為3,5,2,1和4,其中5為最高優先順序。對於下列每種排程演算法,計算其平均程序週轉時間,可忽略程序切換的開銷。

a) 輪轉法。

b) 優先順序排程。

c) 先來先服務(按照10,6,2,4,8次序執行)。

d) 最短作業優先。

對a),假設系統具有多道程式處理能力,每個作業均公平共享CPU時間,對b)到d) ,假設任一時刻只有一個作業執行,直到結束。所有的作業都完全是CPU密集型作業。

答:對於時間片輪轉,在頭10分鐘裡,每個作業獲得1/5的CPU時間。在第10 分鐘時,C結束。在接下來的8分鐘裡,每個作業獲得 1/4 的CPU時間,然後D完成,然後,在接下來的6分鐘內,餘下的3個作業各獲得1/3的CPU時間,直到B結束,以此類推。因此,5個作業的完成時間分別為是10, 18, 24, 28和30, 平均為22分鐘。對於優先順序排程,5最先執行,6分鐘完成。其它作業分別在第14, 24, 26和30分鐘完成,平均為18.8分鐘。如果作業按A->E的次序執行,則分別在第10,16, 18, 22和30分鐘完成,因此,平均為19.2分鐘。最後,最短作業優先排程的完成時間分別為第2, 6, 12, 20和30分鐘,平均為14分鐘。

38、執行在CTSS上的一個程序需要30個時間片完成。該程序必須被調入多少次,包括第一次(在該程序執行之前)?

答:第一次得到 1 個時間片。隨後獲得 2, 4, 8 和 15 個時間片,因此必須經過 5 次交換。

39、能找到一個使CTSS優先順序系統不受隨機回車鏈愚弄的方法嗎?

答:可以檢查程式是否期待輸入,並且對輸入進行處理。不期待輸入也不對輸入進行處理的程式將不得到任何特殊的優先順序提升。

40、a = 1/2的老化演算法用來預測執行時間。先前的四次執行,從最老的一個到最近的一個,其執行時間分別是40ms,20ms,40ms和15ms。下一次的預測時間是多少?

答:預測值的順序為40,30,35,所以下一次是25。(把前兩個資料加一起,除以2,然後把結果和下一個資料加一起,除以2。)

41、一個軟實時系統有4個週期時間,其週期分別為50ms,100ms,200ms和250ms。假設這4個事件分別需要35ms,20ms,10ms和x ms的CPU時間。保持系統可排程的最大x值是多少?

答:所使用的 CPU 的片斷為 35/50 + 20/100 + 10/200 + x/250。為了使得程序可排程,必須是總和小於因此,x必須小於12.5ms。

42、請解釋為什麼兩級排程比較常用。

答:當記憶體太小不能載入所有就緒程序時,就需要使用兩級排程。某些程序被載入記憶體,並且從中選擇一個執行。記憶體中程序會隨著時間調整。這種演算法容易實現也非常有效,另外,時間片輪轉排程並不管程序是否在記憶體中。

43、一個實時系統需要處理兩個語音通訊,每個執行5ms,然後每次突發消耗1ms CPU時間,加上25幀/秒的一個視訊,每一幀需要20ms的CPU時間。這個系統是可排程的嗎?

答:每個語音通訊執行200次/秒,每次突發消耗1毫秒,所以每個語音通訊需要200毫秒/秒或兩個語音通訊需要400毫秒/秒。視訊執行25次/秒,每次使用了20毫秒的時間,總共為500毫秒/秒。它們一起消耗900毫秒/秒,所以還有時間剩餘,系統是可排程的。

44、考慮一個系統,在這個系統中為了核心執行緒排程希望將策略和機制分離。請提出一個實現此目標的手段。

答:核心可以通過任何方式排程程序,但對於每個程序,嚴格按照程序的優先順序順序執行。通過讓使用者程序設定自己的優先順序,讓使用者控制策略,而核心處理機制。

45、在哲學家就餐問題的解法 (圖2-46)中,為什麼在過程 take_forks中將狀態變數置為HUNGRY?

答:如果某個哲學家阻塞,其鄰居稍後能夠在test中檢測其狀態,發現他已經飢餓,當叉子可用時,就可以喚醒他了。

46、考慮圖2-46中的過程pm_forks,假設變數state[i]在對test的兩次呼叫之後而不是之前被置為THINKING,這個改動會對解法有什麼影響?

答:該變化將意味著在哲學家停止進餐後,他的鄰居都不能接著被選擇。事實上,他們永遠不會被選擇。假設哲學家2完成了進餐,他將為哲學家1和3執行test,而兩者都不會被啟動,即使他們兩個都餓了而且兩個叉子都是可用的。類似的,如果哲學家4完成進餐,哲學家3也不會被啟動。他將無法啟動。

47、按照哪一類程序何時開始,讀者-寫者問題可以有若干種方式求解。請詳細描述該問題的三種變體,每一種變體偏好(或不偏好)某一類程序。對每種變體,請指出當一個讀者或寫者訪問資料庫時會發生什麼,以及當一個程序結束對資料庫的訪問後又會發生什麼?

答:變種1:讀者優先。當讀者活躍時,寫者都無法啟動。當一個新的讀者出現時,它可以立即開始除非當前有寫者是活躍的。當寫者完成時,如果有讀者在等待,他們全都啟動,無論是否有寫者存在。

變種2:寫者優先。當有寫者等待時,讀者都不會開始。當最後活躍的程序結束,如果有作者,就啟動它;否則,所有讀者(如果有)全部開始。

變種3:平衡的版本。當有讀者是活躍的,新的讀者可以立即開始。當寫者完成時,新的寫者優先,如果有寫者等待的話。也就是說,一旦開始讀,就一直讀到沒有讀者為止。同樣地,一旦開始作,所有掛起的寫者都被允許執行。

48、請編寫一個shell指令碼,通過讀取檔案的最後一個數字,對之加1,然後再將該數字附在該檔案上,從而生成順序數檔案。在後臺和前臺分別執行該指令碼的一個例項,每個例項訪問相同的檔案。需要多長時間才出現競爭條件?臨界區是什麼?請修改該指令碼以避免競爭(提示:使用In file file.lock鎖住資料檔案。)

答:一個可行的shell指令碼應該如下:

if [ ! –f numbers ]; then echo 0 > numbers; fi
count=0
while (test $count != 200 )
do
    count=‘expr $count + 1’
    n=‘tail –1 numbers’
    expr $n + 1 >>numbers
done

       同時執行該指令碼兩次,通過後臺啟動它一次(使用)和再次在前臺啟動。然後檢查檔案編號。它可能開始看起來會像數字的有序列表,但在某一時刻,由於執行指令碼的兩個副本而建立的競爭條件,它就失去了它的規律。通過對指令碼的每一個副本測試,並在進入關鍵區域之前設定一個鎖,在離開關鍵區域時開啟它,可以避免競爭。可以這樣做:

if ln numbers numbers.lock
then
    n=‘tail –1 numbers’
    expr $n + 1 >>numbers
    rm numbers.lock
fi

       此版本只是當檔案無法訪問時直接跳過,不同的解決方案可以讓程序休眠,忙等待,或僅僅迴圈計數,使得操作成功。

49、假設有一個提供訊號量的作業系統。請實現一個訊息系統,編寫傳送和接收訊息的過程。

答:略。

50、使用管程而不是訊號量來解決哲學家就餐題。

答:略。

51、假設一個大學為了賣弄其政治上的正確性,準備把美國最高法院的信條“平等但隔離其本身就是不平等(Separate but equal is inherently unequal)”既運用在種族上也運在性別上,從而結束校園內長期使用的浴室按性別隔離的做法。但是,為了遷就傳統習慣,學校頒佈法令:當有一個女生在浴室裡,那麼其他女生可以進入,但是男生不行,反之亦然。在每個浴室的門上有一個滑動指示符號,表示當前處於以下三種可能狀態之一:

•空。

•有女生。

•有男生。

用你偏好的程式設計語言編寫下面的過程:

woman_wants_to_enter,man_wants_to_enter,woman_leaves,man_leaves。可以隨意採用所希望的計數器和同步技術。

答:略。

52、重寫圖2-23中的程式,以便能夠處理兩個以上的程序。

答:略。

53、編寫一個使用執行緒並共享一個公共緩衝區的生產者-消費者問題。但是,不要使用訊號量或任何其他用來保護共享資料結構的同步原語。直接讓每個執行緒在需要訪問時就訪問。使用sleep和wakeup來處理滿和空的條件。觀察需要多長時間會出現嚴重的競爭條件。例如,可以讓生產者一會兒列印一個數字,每分鐘列印不要超過一個數字,因為I/O會影響競爭條件。

答:略。