標籤:訊號 signal函數
引言
假如在後台運行一個可執行程式./a.out,如果想終止該程式,通常會按下Ctrl-C,從而產生一個中斷,其實這個過程的實現就是通過訊號完成的。訊號是軟體中斷,它提供了一種處理非同步事件的方法。
(一)
每個訊號都有一個名字,這些名字都以三個字元SIG開頭。例如SIGALARM是鬧鐘訊號,當由alarm函數設定的計時器逾時後產生此訊號。Linux除支援31種不同訊號外,還支援應用程式額外定義訊號。訊號定義在<bits/signum.h>中,也可以通過命令kill -l查看。
(二)訊號的產生
訊號是如何產生的呢,下列方式均可產生訊號:
1、當使用者按某些終端鍵時,引發終端產生的訊號。
2、硬體異常產生訊號:除數為0、無效的記憶體引用等等。
3、進程調用kill(2)函數可將訊號發送給另一個進程或進程組。
4、使用者可用kill(1)命令將訊號發送給其他進程。
5、當檢測到某種軟體條件已經發生,並應將其通知有關進程時也產生訊號。
(三)訊號的處理
進程不能簡單地測試一個變數來判別是否出現了一個訊號,而是必須告訴核心“在此訊號出現時,請執行下列操作”。訊號的處理包括三種方式:忽略訊號、捕捉訊號、執行系統預設動作。
注意:
1、大多數訊號都可以使用忽略訊號的方式進行處理,但對於SIGKILL和SIGSTOP訊號則不能忽略,因為它們向超級使用者提供了使進程終止或停止的可靠方法。
2、為了捕捉訊號,要通知核心在某種訊號發生時調用一個使用者函數。SIGKILL和SIGSTOP訊號不能被捕捉。
3、大多數訊號的系統預設動作是終止進程。
(三)signal函數樣本
訊號機制最簡單的介面就是signal函數。原型如下:
#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);
signo是以SIG三個字母開頭的訊號名。func的值是常量SIG_IGN(忽略此訊號)、常量SIG_DFL(系統預設動作)或當接到此訊號後要調用的函數地址(訊號發生時,調用該函數,即訊號處理常式)。
/* *File Name:signal.c *Author : libing *Mail : [email protected] */#include <stdio.h>#include <stdlib.h>#include <signal.h>static void sig_usr(int);intmain(void){if(signal(SIGUSR1, sig_usr) == SIG_ERR)//signal函數printf("can‘t catch SIGUSR1");if(signal(SIGUSR2, sig_usr) == SIG_ERR)printf("can‘t catch SIGUSR2");for(;;)pause(); /*go to sleep, waiting for signal*/return 0;}static voidsig_usr(int signo){if(signo == SIGUSR1)printf("received SIGUSR1.\n");else if(signo == SIGUSR2)printf("received SIGUSR2.\n");elseprintf("received signal %d\n", signo);}程式測試:
編譯:gcc signal.c -o signal運行:./signal &測試:kill -USR1 8522kill -USR2 8522kill 8522
注意:kill命令和kill函數只是將一個訊號送給一個進程或進程組。訊號是否終止進程則取決於訊號的類型,以及進程是否安排了捕捉該訊號。