Linux 信號

Linux 信號

  • 信號本質:軟中斷信號(signal,又簡稱爲信號)通知進程發生某件事情(會打斷當前的阻塞操作,區處理事情)。信號是進程間通信機制中唯一的異步通信機制,一個進程不必通過任何操作來等待信號的到達。信號機制除了基本通知功能外,還可以傳遞附加信息。

  • 信號的分類:可靠信號:1—31; 非可靠信號:34—64。

  • 信號的生命週期:信號產生 —》信號在進程中註冊 —》信號在進程中註銷 —》信號處理

1.信號的產生:

    硬件產生:例如ctrl+c	ctrl+l	ctrl+z

    軟件產生:通過kill命令產生
  • 用kill -l命令可以察看系統定義的信號列表

    產生方式:
    
    1. 用戶在終端按下某些鍵時,終端驅動程序會發送信號給前臺進程。
    
    2. 硬件異常產生信號,比如內存訪問錯誤。
    
    3. 一個進程調用kill(2)函數可以發送信號給另⼀個進程。
    
    4. 軟件條件產生。
    

2.信號註冊:

  • 信號在進程中註冊指的就是信號值加入到進程的未決信號集sigset_t signal(每個信號佔用一位)中,並且信號所攜帶的信息被保留到未決信號信息鏈的某個sigqueue結構中。只要信號在進程的未決信號集中,表明進程已經知道這些信號的存在,但還沒來得及處理,或者該信號被進程阻塞。

    同一個實時信號可以在同一個進程的未決信號信息鏈中佔有多個sigqueue結構(進程每收到一個實時信號,都會爲它分配一個結構來登記該信號信息;
    同一個非實時信號在進程的未決信號信息鏈中,至多佔有一個sigqueue結構。
    
    總結:
    非可靠信號的註冊:判斷是否有相同的未決信號(判斷pending信號集合位圖是否爲1,),如果有,什麼事情也不做,否則修改進程Pcb中信號的pending位圖,pending位圖置1,添加一個信號的sigqueue結構體節點;
    可靠信號的註冊:判斷是否有相同的未決信號,有就直接添加節點,沒有就修改位圖,添加節點。
    

3.信號註銷:

  • 在其從內核空間返回到用戶空間時會檢測是否有信號等待處理。如果存在未決信號等待處理且該信號沒有被進程阻塞,則在運行相應的信號處理函數前,進程會把信號在未決信號集合中佔有的結構刪除。

注意:內核處理一個進程收到的信號的時機是在一個進程從內核態返回用戶態時。所以,當一個進程在內核態下運行時,軟中斷信號並不立即起作用,要等到將返回用戶態時才處理。進程只有處理完信號纔會返回用戶態,進程在用戶態下不會有未處理完的信號。

  • 信號的三種處理方式:

    1. 進程接受到信號後退出;
    
    2. 進程忽略信號,就像沒發生一樣;
    
    3. 進程收到信號後執行用戶設定用系統調用signal的函數。
    

4.信號的處理安裝:

  • 進程要處理該信號就得在進程中安裝該信號(進程要處理哪個信號,將執行什麼操作)。

    Linux下信號的安裝有兩個函數signal()、sigaction(),其中signal()不支持信息的傳遞,主要用與非可靠信號的安裝,而sigaction()支持信號傳遞信息,主要用與 sigqueue() 系統調用配合使用,當然,sigaction()同樣支持非實時信號的安裝。sigaction()優於signal()主要體現在支持信號帶有參數。
    
  • 信號的自定義處理方式:

     signal(信號編號,處理方式):
    
     1. 默認處理方式		SIG_DFL
    
     2. 忽略處理方式		SIG_IGN
    
     3. 自定義處理方式 	typedef void(*sighandler_t)(int);))  sighandler_t是回調函數
    
     			       	signal(itn signum, sighandler_t handler)
    

在這裏插入圖片描述

  • 信號的阻塞:在信號的生命週期中會出現信號的阻塞等情況(阻止信號被處理)(不處理不代表不註冊)在進程中不標記。
    在這裏插入圖片描述

  • sigprocmask:對信號阻塞集合進行操作的接口

     	SIG_BLOCK		block = block | set	添加阻塞
    
     	SIG_UNBLOCL		block = block & ~ set	解除阻塞
    
     	SIG_SETMASK		block = =mask	設置
    
  • 在所有信號中有兩個信號不能被阻塞。(9號和39號信號不能阻塞)

    接口:
    sigprocmask	 阻塞/解除阻塞信號
    
    sigemptyset	清空信號集合
    
    sigfillset	向集合中添加所有信號
    
    sigaddset 	向集合中添加指定信號
    
    sigismember	判斷信號是否在集合中
    
    siddelset	從信號中移除執行信號
    
    sigpending	獲取未決信號
    (詳細操作見代碼)
    
  • 競態條件:因爲運行時序而導致的數據競爭(競態條件)。
    (函數會被信號打斷)

     1. 函數中梭完成的操作並是一個原子性操作----並且操作的數據是一個全局數據。
    
     2. 不可重入函數:不能在多個時序的運行中重複調用(重複調用有可能會造成數據二義性);
    
     3. 可重入函數:在多個時序下的運行中重複調用,不會造成異常影響(數據二義性問題)。
    
  • 不可重入函數:malloc / free 可中斷睡眠會被信號打斷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章