在上篇部落格中,主要介紹了訊號的基本概念,這次我主要介紹一下與訊號相關的函式以及對它們的應用。
sigaction函式
#include
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
sigaction函式可以讀取和修改與指定訊號相關聯的處理動作。
呼叫成功則返回0,出錯則返回- 1。
signo是指定訊號的編號。
若act指標非空,則根據act修改該訊號的處理動作。
若oact指標非空,則通過oact傳出該訊號原來的處理動作。
act和oact指向sigaction結 構體:
pause函式
#include
int pause(void);
pause函式使呼叫程序掛起直到有訊號遞達。如果訊號的處理動作是終止程序,則程序終止,pause函式沒有機會返回;如果訊號的處理動作是忽略,則程序繼續處於掛起狀態,pause 不返回;如果訊號的處理動作是捕捉,則呼叫了訊號處理函式之後pause返回-1,errno設定為 eintr, 所以pause只有出錯的返回值(想想以前還學過什麼函式只有出錯返回值?)。錯誤碼 eintr表示「被訊號中斷」。
{exec函式、pause函式只會出錯返回。。。}
競態條件與sigsuspend函式
由於非同步事件在任何時候都有可能發生(這裡的非同步事件指出現更高優先順序的程序),如果我們寫程式時考慮不周密,就可能由於時序問題 而導致錯誤,這叫做競態條件 (race condition)。
和pause一樣,sigsuspend沒有成功返回值,只有執行了乙個訊號處理函式之後 sigsuspend才返回,返回值為-1,errno設定為eintr。
呼叫sigsuspend時,程序的訊號遮蔽字由sigmask引數指定,可以通過指定sigmask來臨時解除對某個訊號的遮蔽,然後掛起等待,當sigsuspend返回時,程序的訊號遮蔽字恢復為原來的值,如果原來對該訊號是遮蔽的,從sigsuspend返回後仍然是遮蔽的。
首先,我們來對31個訊號進行捕捉,檢視有那個訊號不能**捉:
**如下:
我們在另外乙個終端中給這個程序傳送訊號,看那個訊號可以是程式結束:
9號訊號(sigkill):
19號訊號(sigstop):
結論:這兩個訊號並不能捕捉
實現自己的my_sleep函式:
這是我們自己實現的my_sleep函式,看下有沒有什麼問題?
系統執行的時序(timing)並不像我們寫程式時所設想的那樣。 雖然alarm(timeout)緊接著的下一行就是pause(),但是無法保證pause()一定會在呼叫alarm(timeout)之後的timeout秒之內被呼叫。由於非同步事件在任何時候都有可能發生,這時由於時序問題就會出現錯誤。
怎樣改進呢?
這時我們就要使用sigsuspend函式,而不是pause函式。
看下面的**:
執行結果:
linux中的訊號
1.什麼是訊號 1.1 訊號是內容受限的一種非同步通訊機制 1 訊號的目的 用來通訊 2 訊號是非同步的 對比硬體中斷 3 訊號本質上是int型數字編號 事先定義好的 1.2 訊號由誰發出 1 使用者在終端按下按鍵 2 硬體異常後由作業系統核心發出訊號 3 使用者使用kill命令向其他程序發出訊號 ...
linux中的訊號1 訊號概述
以下內容源於朱有鵬 物聯網大講堂 課程的學習整理,1 訊號的目的 用來程序間通訊 ipc 程序和核心間的通訊 2 訊號是非同步的 類似於軟體中斷,對比硬體中斷,如按鍵,不知道什麼時候按下 3 訊號本質上是 int型 數字編號 每個編號有特定的含義 內容是十分有限的。1 使用者在終端按下按鍵 2 硬體...
Linux中的訊號處理
突然想起使用sigaction註冊訊號處理函式時,訊號處理函式型別有二個 struct sigaction 通過對上面的sa flags賦值為sa siginfo,讓系統使用多引數的訊號處理函式。在處理函式中,由於傳進來乙個siginfo t的引數,我們可以通過它獲取到哪個程序傳進來的訊息。今天試了...