天天看點

linux 信号與處理

基本概念

信号是事件發生時對程序的通知機制,也就是所謂的軟體中斷。信号和硬體的中斷類似,是軟體層對中斷機制的模拟,在多數情況下是無法預測信号産生的時間,是以軟體層提供了一種處理異步事件的方法。

信号的來源分為硬體來源和軟體來源。

硬體來源:

硬體發生異常,即硬體檢測到錯誤條件并通知核心,随即再由核心發送相應的信号給相關程序,如除數為0、無效的記憶體引用等。

使用者按終端鍵,引起終端産生的信号(比如Ctrl + C鍵産生SIGINT)。

軟體來源:

使用者通過指令殺死,如kill指令。

發生軟體事件, 如程式執行raise, alarm、setitimer、sigqueue等函數。

信号通常是發送給對應的程序,當信号到達後,該程序需要做出相應的處理措施,通常程序會視具體信号執行相應的操作,有三種操作方式。

忽略信号:

  信号到達後、直接忽略,就好像是沒有出該信号,信号對該程序不會産生任何影響。事實上,大多數信号都可以使用這種方式進行處理,但有兩種信号卻決不能被忽略,分别是SIGKILL 和 SIGSTOP。

捕獲信号:

  當信号到達程序後,執行signal()綁定好的信号處理函數。

執行系統預設操作:

  程序不對該信号事件作出處理,而是交由系統進行處理,每一種信号都會有其對應的系統預設的處理方式。

在linux系統中通過​<code>​kill -l​</code>​指令可以檢視到相應的信号。信号編号是從 1 開始,不存在編号為 0 的信号,事實上 kill()函數對信号編号 0 有着特殊的應用。

linux 信号與處理

注意:括号" ) "前面的數字對應該信号的編号,編号 1~31 所對應的是不可靠信号,編号 34~64 對應的是可靠信号,從圖中可知,可靠信号并沒有一個具體對應的名字,而是使用了 SIGRTMIN+N 或 SIGRTMAXN 的方式來表示。其中32和33空缺。

不可靠信号表

<col>

名稱

解釋

預設動作

1

SIGHUP

挂起

2

SIGINT

中斷

3

SIGQUIT

退出

4

SIGILL

非法指令

5

SIGTRAP

斷點或陷阱指令

6

SIGABRT

abort發出的信号

7

SIGBUS

非法記憶體通路

8

SIGFPE

浮點異常

9

SIGKILL

kill信号

不能被忽略、處理和阻塞

10

SIGUSR1

使用者信号1

11

SIGSEGV

無效記憶體通路

12

SIGUSR2

使用者信号2

13

SIGPIPE

管道破損,沒有讀端的管道寫資料

14

SIGALRM

alarm發出的信号

15

SIGTERM

終止信号

16

SIGSTKFLT

棧溢出

17

SIGCHLD

子程序退出

預設忽略

18

SIGCONT

程序繼續

19

SIGSTOP

程序停止

20

SIGTSTP

21

SIGTTIN

程序停止,背景程序從終端讀資料時

22

SIGTTOU

程序停止,背景程序想終端寫資料時

23

SIGURG

I/O有緊急資料到達目前程序

24

SIGXCPU

程序的CPU時間片到期

25

SIGXFSZ

檔案大小的超出上限

26

SIGVTALRM

虛拟時鐘逾時

27

SIGPROF

profile時鐘逾時

28

SIGWINCH

視窗大小改變

29

SIGIO

I/O相關

30

SIGPWR

關機

31

SIGSYS

系統調用異常

signal()

"signal.h"信号處理庫提供了signal函數,用來捕獲突發事件。以下是 signal() 函數的文法ads。

signum:可使用信号名(宏)或信号的數字編号,建議使用信号名。

handler:參數 handler 既可以設定為使用者自定義的函數,也可以設定為 SIG_IGN 或 SIG_DFL,SIG_IGN 表示此程序需要忽略該信号,SIG_DFL 則表示設定為系統預設操作。

raise()

有時程序需要向自身發送信号,raise()函數可用于實作這一要求.

sig:需要發送的信号。

sigaction()

除了signal()之外,sigaction()系統調用是設定信号處理方式的另一選擇,雖然 signal()函數簡單好用,而 sigaction()更為複雜,但作為回報,sigaction()也更具靈活性以及移植性。

signum:需要設定的信号,除了 SIGKILL 信号和 SIGSTOP 信号之外的任何信号。

act:參數 act 不為 NULL,則表示需要為信号設定新的處理方式;如果參數 act 為 NULL,則表示無需改變信号目前的處理方式

oldact:參數oldact 不為 NULL,則會将信号之前的處理方式等資訊通過參數 oldact 傳回出來;如果無意擷取此類資訊,那麼可将該參數設定為 NULL。

傳回值:成功傳回 0;失敗将傳回-1,并設定 errno。

struct sigaction 結構體

sa_handler:指定信号處理函數,與 signal()函數的 handler 參數相同。

sa_sigaction:也用于指定信号處理函數,這是一個替代的信号處理函數。

sa_mask:參數 sa_mask 定義了一組信号。

sa_restorer:該成員已過時,不要再使用了。

sa_flags:參數 sa_flags 指定了一組标志,這些标志用于控制信号的處理過程。

kill()

kill()系統調用可将信号發送給指定的程序或程序組中的每一個程序。

pid:參數 pid 為正數的情況下,用于指定接收此信号的程序 pid。

sig:參數 sig 指定需要發送的信号,也可設定為 0,如果參數 sig 設定為 0 則表示不發送信号,但任執行錯誤檢查,這通常可用于檢查參數 pid 指定的程序是否存在。

alarm()

使用 alarm()函數可以設定一個定時器(鬧鐘),當定時器定時時間到時,核心會向程序發送 SIGALRM信号。

seconds:設定定時時間,以秒為機關;如果參數 seconds 等于 0,則表示取消之前設定的 alarm 鬧鐘。

傳回值:如果在調用 alarm()時,之前已經為該程序設定了 alarm 鬧鐘還沒有逾時,則該鬧鐘的剩餘值作為本次 alarm()函數調用的傳回值,之前設定的鬧鐘則被新的替代;否則傳回 0。

pause()

pause()系統調用可以使得程序暫停運作、進入休眠狀态,直到程序捕獲到一個信号為止,隻有執行了信号處理函數并從其傳回時,pause()才傳回,在這種情況下,pause()傳回-1,并且将 errno 設定為EINTR。

使用案例

demo1

下一篇: 架構選型

繼續閱讀