實現睡眠函式mysleep

2021-08-03 09:57:50 字數 1663 閱讀 2562



1. 普通版本的 mysleep 函式(有 bug 存在)

執行結果如下:

我們可以發現當我們的**執行以後,螢幕上輸出很多的 using mysleep sleep! ,而且在最後一行每隔三秒列印一次,且一直列印直到我們強制停止。

審視 「mysleep」 程式,設想這樣的時序:

① 註冊 sigalrm 訊號的處理函式。

② 呼叫 alarm(nsecs) 設定鬧鐘。

③ 核心排程優先順序更高的程序取代當前程序執行,並且優先順序更高的程序有很多個,每個都要執行很長時間。

④ nsecs 秒鐘之後鬧鐘超時了,核心傳送 sigalrm 訊號給這個程序,處於未決狀態。

⑤ 優先順序更高的程序執行完了,核心要排程回這個程序執行。sigalrm 訊號遞達,執行處理函式 sig_alrm 之後再次進入核心。

⑥ 返回這個程序的主控制流程,alarm(nsecs) 返回,呼叫 pause() 掛起等待。

⑦ 可是 sigalrm 訊號已經處理完了,還等待什麼呢?

出現這個問題的根本原因是系統執行的時序 (timing) 並不像我們寫程式時所設想的那樣。雖然 alarm(nsecs) 緊接著的下一行就是 pause(),但是無法保證 pause() 一定會在呼叫alarm(nsecs) 之後的 nsecs 秒之內被呼叫。由於非同步事件在任何時候都有可能發生(這裡的非同步事件指出現更高優先順序的程序),如果我們寫程式時考慮不周密,就可能由於時序問題而導致錯誤,這叫做競態條件 (race condition)。

2. 規避競態條件的 mysleep

執行結果如下:

結果相同,證明我們也實現了 mysleep。

兩者的區別:

第一種 mysleep 的實現我們說存在時序問題,會在某種程度上產生 bug,那麼第二種方法是如何規避的呢?它將「解除訊號遮蔽」和「掛起等待訊號」這兩步能合併成乙個原子操作,是因為呼叫了 sigsuspend 函式,sigsuspend 包含了 pause 的掛起等待功能,同時解決了競態條件的問題,因此在對時序要求嚴格的場合下都應該呼叫 sigsuspend 而不是pause。

自實現睡眠函式

1.這段 注意的地方 alarm 函式不是阻塞函式,定時之後,程式會繼續往下執行 pause 阻塞函式,函式被呼叫呼叫後,主動造成程式掛起。2.這個地方很容易想歪 當時的問題是這樣 加入該程式在 執行完38 後失去cpu資源,那麼當它再次獲得cpu資源時且訊號已經發出,程式會不會喚醒,答案是不會。因...

unix程式設計實驗五 實現mysleep函式

實驗五 實現mysleep函式 實驗描述 函式名字和原型 unsigned int mysleep unsigned int 該函式的功能要求與unix的sleep函式一樣。要求 1 使用alarm函式實現定時。2 必須正確處理mysleep函式中的鬧鐘與呼叫者可能設定的鬧鐘之間的關係。例如,如何解...

Linux中的mysleep函式

第乙個版本 1 main函式呼叫mysleep函式,後者呼叫sigaction註冊了sigalrm訊號的處理函式handler。2 呼叫alarm timeout 設定鬧鐘。3 呼叫pause等待,核心切換到別的程序執行。4 timeout秒之後,鬧鐘超時,核心發sigalrm給這個程序。5 從核心...