APUE——信號基礎以及信號的響應

1.信號基礎

1.1 信號函數

#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);  這是可靠寫法

void (* signal( int signo, void (*func)(int) )  )(int);

函數名      :signal

函數參數   :int signo, void (*func)(int)

返回值類型:void (*)(int);

信號的忽略: 信號忽略的核心是將mask中設置0,導致後續與操作始終是0,SIGKILL與SIGSTOP不能被忽略!另外,如果忽略某些由硬件異常產生的信號(例如除以0),則進程的運行行爲是未定義的。
信號的默認動作:大多數的信號處理函數是終止進程!
信號捕捉:爲了做到這一點,要通知內核在某種信號發生時調用一個用戶函數。在用戶函數中,可執行用戶希望對這種事件進行的處理。注意,不能捕捉SIGKILL和SIGSTOP信號。
信號與中斷:信號依賴於中斷!
信號與系統調用:信號是可以打斷系統調用的,所以在執行調用函數的時候,需要增加判斷,errno是否是EINTR,如果是則continue,否則perror(“error”)

1.2 信號產生

產生信號的條件:

  1. 當用戶按某些終端鍵時,引發終端產生的信號。
  2. 硬件異常產生信號。
  3. 進程調用kill(2)函數可將信號發送給另一個進程或進程組。(自然,對此有所限制:接收信號進程和發送信號進程的所有者必須相同,或者發送信號進程的所有者必須是超級用戶。)
  4. 用戶可用kill(1)命令將信號發送給其他進程。
  5. 當檢測到某種軟件條件已經發生,並應將其通知有關進程時也產生信號。(這裏指的不是硬件產生的條件,而是軟件條件。)
    在信號產生(generation)和遞送(delivery)之間的時間間隔,稱信號是未決的(pending)

1.3可重入函數

信號的函數執行是可以被打斷的,所以會涉及到函數的可重入,系統調用函數都是可重入的,後續在sigaction裏可以設置信號處理函數會自動重啓被打斷的系統調用,一部分庫函數也是可重入的
可衝重入的函數列表如下:在這裏插入圖片描述
(a)已知它們使用靜態數據結構,(b)它們調用malloc或free,或(c)它們是標準I/O函數。

1.4 實時信號與非實時信號

在這裏插入圖片描述
其中1-31 是非實時信號,是不可靠信號, 34-64是實時信號,是可靠的
非實時信號是通過pending位圖來實現,同時出現多個信號會覆蓋
實時信號是有隊列的,可以ulimit -a來查看pending最大個數,同時出現多個信號會排隊

2. 信號響應策略

信號響應的過程

  1. 信號從接收到響應是有一個延遲的,因爲需要等待中斷
  2. 標準信號是沒有嚴格的響應順序的
  3. 因爲pending位圖的關係,導致如果連續多個標準信號到來,pending會被覆蓋,所以會出現丟失,沒有隊列!

注意點:

  1. 進程中的信號位圖的初始時刻pending均爲0,mask均爲1,後續可以通過sigaction等來修改
  2. 信號在用戶態切換到內核態前要進行位與操作,判斷是否有信號
  3. 只有當有中斷到來後,當前進程進入內核態,信號本身到來並不能立刻響應
  4. 進程在內核態發現信號後,將mask與pending均置0,當信號處理函數執行完後,會將mask置1,pending置0!
    在這裏插入圖片描述
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章