產生原因:仍然以前文實現的sleep函數為例,如果進程在執行完alarm函數后,突然失去CPU,被阻塞等待(這是有可能的,進程在執行過程中,若非原子操作,都有可能隨時失去CPU),如果失去CPU的時間大于了sleep函數需要睡眠的時間,則此時在執行pause函數前,信號已經到了,因此會先處理信號(軟中斷,而不是先執行pause函數),在信號處理完后,再去執行pause函數,此時進程會被永遠掛起,不會被喚醒,因為SIGALRM信號已經被處理了。時序競態:即由于進程之間執行的順序不同,導致同一個進程多次運行后產生了不同結果的現象。如上述sleep函數,有時執行結果是正確的,有時卻會導致進程永遠被掛起,因此這就是一個時序競態問題。因此需要重新對該函數進行改進。
1. 注冊SIGALRM信號處理函數(sigaction...)
?2. 調用alarm(1) 函數設定鬧鐘1秒。
3. 函數調用剛結束,開始倒計時1秒。當前進程失去cpu,內核調度優先級高的進程(有多個)取代當前進程。當前進程無法獲得cpu,進入就緒態等待cpu。
4. 1秒后,鬧鐘超時,內核向當前進程發送SIGALRM信號(自然定時法,與進程狀態無關),高優先級進程尚未執行完,當前進程仍處于就緒態,信號無法處理(未決)
?5. 優先級高的進程執行完,當前進程獲得cpu資源,內核調度回當前進程執行。SIGALRM信號遞達,信號設置捕捉,執行處理函數sig_alarm。
6. 信號處理函數執行結束,返回當前進程主控流程,pause()被調用掛起等待。(欲等待alarm函數發送的SIGALRM信號將自己喚醒)
7. SIGALRM信號已經處理完畢,pause不會等到。