linux中在執行一些程序時有時肯定因為一些內部或外部的原因需要中斷,這就是軟中斷,通過訊號來實現。下面介紹一些中斷,後續會有增加,可能有不足的地方望指正。
一、傳統的訊號處理方式signal()函式,這一函式相對比較簡單:
void (*signal(int signo, void (*func)(int)))(int);
可分解為:
typedef void sigfunc(int);
sigfunc *signal(int signo, sigfunc *));
第乙個引數指定訊號的值,第二個引數指定針對前面訊號值的處理,可以忽略該訊號(引數設為sig_ign);可以採用系統預設方式處理訊號(引數設為sig_dfl);也可以自己實現處理方式(引數指定乙個函式位址)。
由於signal()函式的功能有限,在此就不詳細描述為何有限。unix又引進了sigaction()函式,它包含了signal的所有功能,並且有很多的選擇性。下面就來介紹:
二、sigaction()函式
int sigaction(int signo,const struct sigaction * restrict act,struct sigaction * restrict oldact));
第二和第三個引數都是關於sigaction陣列的,下面主要介紹:
struct sigaction
sa_handler和signal一樣是sig_ign或sig_dfl或是處理訊號的函式,如果是最後乙個,則sa_mask欄位說明了乙個訊號集,在呼叫該訊號捕捉函式之前,這一訊號集要加到程序的訊號遮蔽字中。僅當從訊號捕捉函式返回時再將程序的訊號遮蔽字復位為原先值。這樣,在呼叫訊號處理程式時就能阻塞某些訊號。在訊號處理程式被呼叫時,作業系統建立的新訊號遮蔽字包括正被遞送的訊號。因此保證了在處理乙個給定的訊號時,如果這種訊號再次發生,那麼它會被阻塞到對前乙個訊號的處理結束為止。
sa_flags引數
詳解參見:
sa_sigaction欄位是乙個替代的訊號處理程式,當在sigaction結構中使用了sa_siginfo標誌時,使用該訊號處理程式。對於sa_sigaction欄位和sa_handler欄位這兩者,其實現可能使用同一儲存區,所以應用程式只能一次使用這兩個欄位中的乙個。
通常,按下列方式呼叫訊號處理程式:
void handler(int signo);
但是,如果設定了sa_siginfo標誌,那麼按下列方式呼叫訊號處理程式:
void handler(int signo, siginfo_t *info, void *context);
siginfo_t結構包含了訊號產生原因的有關資訊。該結構的大致樣式如下所示:
struct siginfo ;
各種訊號的si_code值(包括上面的相關資料結構和標誌選項),可通過man sigaction命令進行檢視。
若訊號是sigchld,則將設定si_pid、si_status和si_uid欄位。
若訊號是sigill或sigsegv,則si_addr包含造成故障的根源位址,儘管該位址可能並不準確。
若訊號是sigpoll,那麼si_band欄位將包含streams訊息的優先順序(priority band),該訊息產生poll_in、poll_out或poll_msg事件。
si_errno欄位包含錯誤編號,它對應於引發訊號產生的條件,並由實現定義。
訊號處理程式的context引數是無型別指標,它可被強制轉換為ucntext_t結構型別,用於標識訊號傳遞時程序的上下文。
三、sigprocmask()阻塞訊號函式
在任何時候乙個程序都有一些訊號被阻塞。注意是阻塞而不是忽略。這個訊號就稱為訊號擋板,通過sigprocmask可以修改這個被阻塞的訊號集。
int sigprocmask(int how, const sigset_t *restrict
set, sigset_t *restrict oldset);
how:用於指定訊號修改的方式,可能選擇有三種
sig_block//將set所指向的訊號集中包含的訊號加到當前的訊號掩碼中。即訊號掩碼和set訊號集進行或操作。
sig_unblock//將set所指向的訊號集中包含的訊號從當前的訊號掩碼中刪除。即訊號掩碼和set進行與操作。
sig_setmask //將set的值設定為新的程序訊號掩碼。即set對訊號掩碼進行了賦值操作。
set:為指向訊號集的指標,在此專指新設的訊號集,如果僅想讀取現在的遮蔽值,可將其置為null。
oldset:也是指向訊號集的指標,在此存放原來的訊號集。可用來檢測訊號掩碼中存在什麼訊號。
sigsetops構造訊號集:
sigemptyset()初始化時設定的優先順序設為 empty ,與所有訊號設定.
sigfillset()初始化設定,包括所有訊號.
sigaddset()和sigdelset()訊號 signum 中新增和刪除分別設定.
注意:
......
sigprocmask(sig_block,&sigs,&prevsigs);
//...modify data structure here...
sigprocmask(sig_set,*prevsigs,null);
......
這裡在修改訊號擋板時會儲存先前的設定 prevsigs,然後在對資料進行修改,最後用儲存的設定prevsigs來恢復原來的訊號擋板。除非目的就是修改獲取修改獲取的資源,否則釋放資源時恢復獲取時的狀態是個好習慣。 Linux程序訊號筆記總結
訊號 作用 為了通知我們某個事件的發生 就是乙個軟中斷,通知程序發生某件事情,打斷程序當前的操作,去先處理這個事件 必須認識訊號,訊號不是立即處理的。而實現記錄下來,選擇乙個合適的事機處理 訊號必須有預設的處理方式,當然也可以改變。訊號是可以被阻塞,暫時不處理 訊號的週期性 生命週期 產生 註冊 登...
Linux 程序通訊之 訊號和訊號量總結
如今最經常使用的程序間通訊的方式有 訊號,訊號量,訊息佇列,共享記憶體。所謂程序通訊,就是不同程序之間進行一些 接觸 這種接觸有簡單,也有複雜。機制不同,複雜度也不一樣。通訊是乙個廣義上的意義,不僅僅指傳遞一些massege。他們的用法是基本相同的,所以僅僅要掌握了一種的用法,然後記住其他的用法就能...
linux訊號 阻塞訊號
1.訊號在核心中的表示 我們知道了訊號產生的各種原因,而實際執行訊號處理的動作,叫做訊號遞達 delivery 訊號從產生到遞達之間的狀態,稱為訊號未決 pending 程序可以選擇阻塞 block 某個訊號。被阻塞的訊號產生時將保持在未決狀態,直到程序解除對此訊號的阻塞,才執行遞達的動作。注意,阻...