#Linux#進程間通信# 信號(sinal)

在計算機科學中,信號是Unix、類Unix以及其他POSIX兼容的操作系統中進程間通訊的一種有限制的方式。它是一種異步的通知機制,用來提醒進程一個事件已經發生。當一個信號發送給一個進程,操作系統中斷了進程正常的控制流程,此時,任何非原子操作都將被中斷。如果進程定義了信號的處理函數,那麼它將被執行,否則就執行默認的處理函數。

軟中斷信號(signal,又簡稱爲信號)用來通知進程發生了異步事件。進程之間可以互相通過系統調用kill發送軟中斷信號。內核也可以因爲內部事件而給進程發送信號,通知進程發生了某個事件。注意,信號只是用來通知某進程發生了什麼事件,並不給該進程傳遞任何數據。收到信號的進程對各種信號有不同的處理方法。處理方法可以分爲三類:第一種是類似中斷的處理程序,對於需要處理的信號,進程可以指定處理函數,由該函數來處理。第二種方法是,忽略某個信號,對該信號不做任何處理,就象未發生過一樣。第三種方法是,對該信號的處理保留系統的默認值,這種缺省操作,對大部分的信 號的缺省操作是使得進程終止。進程通過系統調用signal來指定進程對某個信號的處理行爲。在進程表的表項中有一個軟中斷信號域,該域中每一位對應一個信號,當有信號發送給進程時,對應位置位。由此可以看出,進程對不同的信號可以同時保留,但對於同一個信號,進程並不知道在處理之前來過多少個。

信號與信號量這兩個名詞只有一字之差,有時候我們會很容易聯想到這兩個東西是不是一個東西,然而卻是完全不同的兩個概念。

  • 信號:是由用戶、系統或者進程發送給目標進程的信息,以通知目標進程某個狀態的改變或系統異常。通知進程產生了某個事件
  • 信號量信號量是一個特殊的變量,它的本質是計數器,信號量裏面記錄了臨界資源的數目,有多少數目,信號量的值就爲多少,進程對其訪問都是原子操作(pv操作,p:佔用資源,v:釋放資源)。它的作用就是,調協進程對共享資源的訪問,讓一個臨界區同一時間只有一個進程在訪問它。用來同步進程的(用來調協進程對共享資源的訪問的)

以下情況會引發信號

  • 鍵盤事件  如ctrl+c產生SIGINT信號,ctrl+\產生SIGQUIT信號,ctrl+z產生SIGTSTP信號
  • 硬件異常  硬件出現故障。非法訪問內存(段錯誤)、除0(浮點數例外)、內存對齊錯誤(總線錯誤)會產生一個信號,由硬件檢測並通知內核,然後內核向進程發送適當的信號,比如執行了除以零的指令,進程訪問了非法內存地址,cpu的運算單元都會產生異常,內核將這個異常解釋成一個個信號發送給進程。
  • 系統調用  kill、abort、raise等系統函數調用
  • 軟件條件  使用定時器alarm
  • 系統命令   kill

信號是異步事件,當信號到達時,保存當前的執行環境,轉去執行信號處理函數,當信號處理函數完畢,恢復現場,繼續執行。

進程收到信號的三種處理方式

  • 默認:執行信號的默認處理動作,如果是系統SIGINT的話,那就會中斷這個進程
  • 忽略 :信號來了我們不處理,裝作沒看到   SIGKILL  SIGSTOP 不能忽略
  • 捕獲並處理 :當信號來了,執行我們自己寫的代碼提供一個信號處理函數,要求內核在處理信號時切換到用戶態執行這個處理函數(捕獲信號這個動作是需要我們完成的)  SIGKILL SIGSTOP 不能捕獲

註冊信號

typedef void  (* sighandler_t) (int);
sighandler_t signal (int signum   /*要註冊的信號*/, sighandler_t handler /*信號執行函數*/);

信號捕捉

  • (1)首先在用戶正常執行主控制流程由於中斷,異常或系統調用而直接進入內核態進行處理處理這種異常,
  • (2)內核處理完異常就準備返回用戶態了,在這之前會看當前進程有沒有可以抵達的信號,如果有就對可遞達的信號進行處理,
  • (3)如果信號的處理函數是用戶自定義的就返回用戶態去執行用戶自定義的信號處理函數
  • (4)信號處理函數執行完之後,會調用一個特殊的系統調用函數sigreturn而再一次進入內核態,執行這個系統調用
  • (5)這個系統調用完成之後,就會返回主控制流程被中斷的地方繼續執行下面的代碼
  • (6)執行主控制流程的時候如果再次遇到異常、中斷或系統調用就繼續回到(1),繼續執行下面的流程

 

可靠信號和不可靠信號

實時信號 : 就是可靠信號
非實時信號:不可靠信號

不可靠信號

  • 1-31  都是不可靠的,會出現信號丟失現象
  • Linux的信號繼承自早期的Unix信號,Unix信號的缺陷
  • 信號處理函數執行完畢,信號恢復成默認處理方式(Linux已經改進)
  • 會出現信號丟失,信號不排隊

可靠信號

  • 34-64重新設計的一套信號集合
  • 不會出現信號丟失,支持排隊,信號處理函數執行完畢,不會恢復成缺省處理方式

 

【 kill -l 】 這個命令就可以查看所有的信號啦,現在信號已經增加到65個了,但是在這裏我要提一下,從33-64這些信號一般不會採用,這是爲了區分可靠信號和不可靠信號而新增加的32個信號。

cll@cll-linux:~ $ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

【man 7 signal 】 這個命令使用man手冊查看,因爲在第七頁,所以直接用 man 7。常用標準信號如下:

Standard signals
       Linux  supports the standard signals listed below.  Several signal num‐
       bers are architecture-dependent, as indicated in  the  "Value"  column.
       (Where three values are given, the first one is usually valid for alpha
       and sparc, the middle one for x86, arm, and most  other  architectures,
       and  the  last one for mips.  (Values for parisc are not shown; see the
       Linux kernel source for signal numbering on that  architecture.)   A  -
       denotes that a signal is absent on the corresponding architecture.)

       First the signals described in the original POSIX.1-1990 standard.

       Signal     Value     Action   Comment
       ──────────────────────────────────────────────────────────────────────
       SIGHUP        1       Term    Hangup detected on controlling terminal
                                     or death of controlling process
       SIGINT        2       Term    Interrupt from keyboard
       SIGQUIT       3       Core    Quit from keyboard
       SIGILL        4       Core    Illegal Instruction
       SIGABRT       6       Core    Abort signal from abort(3)
       SIGFPE        8       Core    Floating point exception
       SIGKILL       9       Term    Kill signal
       SIGSEGV      11       Core    Invalid memory reference
       SIGPIPE      13       Term    Broken pipe: write to pipe with no
                                     readers
       SIGALRM      14       Term    Timer signal from alarm(2)
       SIGTERM      15       Term    Termination signal
       SIGUSR1   30,10,16    Term    User-defined signal 1
       SIGUSR2   31,12,17    Term    User-defined signal 2
       SIGCHLD   20,17,18    Ign     Child stopped or terminated
       SIGCONT   19,18,25    Cont    Continue if stopped
       SIGSTOP   17,19,23    Stop    Stop process
       SIGTSTP   18,20,24    Stop    Stop typed at terminal
       SIGTTIN   21,21,26    Stop    Terminal input for background process
       SIGTTOU   22,22,27    Stop    Terminal output for background process

       The signals SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.

       Next  the  signals  not  in  the POSIX.1-1990 standard but described in
 Manual page signal(7) line 134 (press h for help or q to quit)

在以上的信號中,

程序不可捕獲、阻塞或忽略的信號 9) SIGKILL,19) SIGSTOP
不能恢復至默認動作的信號 4) SIGILL,5) SIGTRAP
默認會導致進程流產的信號 6) SIGABRT,7) SIGBUS,8) SIGFPE,4) SIGILL,29) SIGIO,3) SIGQUIT,11) SIGSEGV,5) SIGTRAP,24) SIGXCPU,25) SIGXFSZ
默認會導致進程退出的信號 14) SIGALRM,1) SIGHUP,2) SIGINT,9) SIGKILL,13) SIGPIPE,SIGPOLL(當某個事件發送給Pollable Device的時候發送, 部分系統),27) SIGPROF,31) SIGSYS,15) SIGTERM,10) SIGUSR1,12) SIGUSR2,26) SIGVTALRM
默認會導致進程停止的信號 19) SIGSTOP,20) SIGTSTP,21) SIGTTIN,22) SIGTTOU
默認進程忽略的信號 17) SIGCHLD,30) SIGPWR,23) SIGURG,28) SIGWINCH
  • 此外,SIGIO在SVR4是退出,在4.3BSD中是忽略;
  • SIGCONT在進程掛起時是繼續,否則是忽略,不能被阻塞。

默認動作:

  •               Term:終止進程
  •               Ign: 忽略信號 (默認即時對該種信號忽略操作)
  •               Core:終止進程,生成Core文件。(查驗進程死亡原因, 用於gdb調試)
  •               Stop:停止(暫停)進程
  •               Cont:繼續運行進程

 

kill、killall、kill(pid_t pid, int sig);

kill、killall

這兩個命令是用來向進程發送信號的。kill 命令需要進程號作爲參數,而 killall 需要進程名稱。另外,還可以在這兩個命令後附加要發送信號序號作爲參數。默認情況下,它們都向相關進程發送信號 15 (TERM)。例如,如果你想要終止 PID 爲 666的進程,請輸入以下命令:

kill 666

如果您要向它發送信號 9 (SIGKILL),請輸入:

kill -9 666

假設您知道想要終止的進程的命令名稱。您可以通過該名稱來終止它,而不用再使用 ps 找出該進程的進程號:

killall -9 your-process-name

 

kill(pid_t pid, int sig);

用於向任何進程組或進程發送信號。

頭文件用法:

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);

參數:
pid:可能選擇有以下四種

  • 1. pid大於零時,pid是信號欲送往的進程的標識。
  • 2. pid等於零時,信號將送往所有與調用kill()的那個進程屬同一個使用組的進程。
  • 3. pid等於-1時,信號將送往所有調用進程有權給其發送信號的進程,除了進程1(init)。
  • 4. pid小於-1時,信號將送往以-pid爲組標識的進程。

sig:準備發送的信號代碼,假如其值爲零則沒有任何信號送出,但是系統會執行錯誤檢查,通常會利用sig值爲零來檢驗某個進程是否仍在執行。

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