IPC-信號處理

基本規(guī)則

  • 信號可以由系統(tǒng)內(nèi)核程序發(fā)出,也能由某些進程發(fā)送,但是大部分時候都是由內(nèi)核程序發(fā)出.
  • 當一個信號正在被處理時,所有同樣的信號都將暫時擱置,知道這個信號處理完成.
  • 進程接受到核心程序發(fā)出的信號后,處置的方式:
    1. 忽略
    2. 執(zhí)行一個處理此信號的函數(shù)
    3. 暫停進程的執(zhí)行
    4. 重新啟動剛才被暫停的那個進程
    5. 采用系統(tǒng)默認的行動,大部分信號的默認操作都是終止進程的執(zhí)行.有些信號除了會終止進程的執(zhí)行,還會留下一個叫core的文件.這個過程叫做內(nèi)核轉(zhuǎn)儲core dump.這個文件存有進程當時在內(nèi)存中的內(nèi)容,通常用于事后查錯.

信號類型

  • 可用 kill -l查看系統(tǒng)中預定義的信號
  • 表1,下表是Linux支持的POSIX.1中的信號.

| 信號| 值 | 動作 | 意義 |
| ------------- |:-------------:| -----:|
| SIGFPE | 8 | C | 浮動溢出錯誤|
| SIGKILL | 9 | AEF | 刪除一個或一組進程,本信號不能忽略 |
| SIGSEGV | 11 | C | 不合法的內(nèi)存引用 |
| SIGPIPE |13 | A | 斷開的管道,即讀管道的進程非正常終止了 |
| SIGALRM | 14 | A | 時鐘,用來測量進程的真實時間(不是CPU時間),alarm系統(tǒng)調(diào)用就是用來設定此信號 |
| SIGTERM | 15 | A | 終止進程,kill系統(tǒng)調(diào)用就發(fā)送這個信號 |
| SIGUSR1 | 30,10,16 | A |用戶自定義信號 |
| SIGUSR2 | 31,12,17 | A |用戶自定義信號 |
| SIGCHLD | 20,17,18 | B |子進程暫停或終止 |
| SIGCONT | 19,18,25 | |如果進程暫停,那么繼續(xù)執(zhí)行 |
| SIGSTOP | 17,19,23 |DEF |暫停進程 |
| SIGTSTP | 18,20,24 | D |把停止信號發(fā)送給聯(lián)機會話進程,通常由Ctrl+Z來產(chǎn)生此信號 |
| SIGTTIN | 21,21,26 | D |后臺執(zhí)行中的進程要從控制終端讀取數(shù)據(jù) |
| SIGTTOU |22,22,27 | D |后臺執(zhí)行中的進程企圖對控制終端寫入數(shù)據(jù) |

  • 表2, linux還支持的一些其他信號

| 信號| 值 | 動作 | 意義 |
| ------------- |:-------------:| -----:|
|SIGTRAP|5|CG|程序跟蹤中斷點,這是給調(diào)試程序(如gdb)專用的信號|
|SIGIOT|6|CG|輸入輸出中斷點,通常是由于硬件故障|
|SIGEMT|7,-7|G|硬件仿真程序捕獲|
|SIGBUS|10,7,10|AG|總線錯誤|
|SIGSYS|12,-12|G|系統(tǒng)調(diào)用參數(shù)錯誤SVID|
|SIGSTKFLT|-,16,-|AG|協(xié)處理器堆棧錯誤|
|SIGURG|16,23,21|BG|這個信號通知系統(tǒng)有要求立即處理的SOCKET|
|SIGIO|23,29,22|AG|I/O操作可以執(zhí)行,|
|SIGPOLL||AG|與SIGIO同義|
|SIGCLD|-,-,18|G|與SIGCHLD同義|
|SIGXCPU|24,24,30|AG|進程超出了所設定給它的最大CPU使用時限|
|SIGXFSZ|25,25,31|AG|進程超出了所設定給它的最大文件極限|
|SIGVTALRM|26,26,28|AG|用以測量進程的虛擬時間(實際被執(zhí)行進程的時間)|
|SIGPROF|27,27,29|AG|用以測量進程的概括時間(指虛擬時間加核心程序執(zhí)行進程實際時間)|
|SIGPWR|29,30,19|AG|電源故障|
|SIGINFO|29,-,-|G|與SIGPWR同義|
|SIGLOST|-,-,-|AG|文件鎖丟失|
|SIGWINCH|28,28,20|BG|X Window窗口改變大小|
|SIGUNUSED|-,31,-|AG|未使用的信號|

  • 說明:
  • 每一個信號值分為三列,信號是與CPU相關的,第一個alpha和sparc上的信號值,第二個是i386和PowerPC上的信號值,第三個是mips上的信號值.
  • 信號值為"-"表示沒有此信號
  • 信號值29在alpha上為SIGINFO/SIGPWR, 在spac上為SIGLOST
  • 動作一欄中的字母意義如下:
    A 終止進程
    B 忽略信號
    C 內(nèi)核轉(zhuǎn)儲
    D 暫停進程
    E 信號不能俘獲
    F 信號不能被忽略
    G 不是POSIX.1 兼容信號
  • SIGIO 和SIGLOST 有相同的信號值,SIGLOST是在內(nèi)核中定義的,但是有些應用程序仍舊把信號值29當作SIGLOST

進程處理信號的方式

  • 除非進程收到的信號是SIGKILL之類只能采取默認行動的信號, 否則多半都是由進程自行決定, 主要有4中方式:
  1. 系統(tǒng)默認處理,一般的默認處理就是終止運行
  2. 忽略信號
  3. 暫停擱置信號
  4. 利用系統(tǒng)調(diào)用 signal 設定處理信號的函數(shù)

注冊信號調(diào)用函數(shù)

//參數(shù)signumber表示所注冊函數(shù)針對的信號,其取值為上表1表2種的信號名
//參數(shù)func通常是指向調(diào)用函數(shù)的函數(shù)指針,它指定收到信號后進程所采取的行動,這個就是信號處理函數(shù),此函數(shù)有一個整數(shù)參數(shù)且返回值為void
//這個信號處理函數(shù)可能是用戶自定義的函數(shù),或者取值SIG_IGN或SIG_DFL
//SIG_IGN表示忽略signumber所指出的信號
//SIG_DFL表示調(diào)用系統(tǒng)定義的缺省處理
//信號處理函數(shù)的參數(shù)是要處理的信號的信號值
//不能為SIGKILL和SIGSTOP設置信號處理函數(shù)
//signal函數(shù)的返回值類型同參數(shù)func,其正確返回值應為上次信號的處理函數(shù),錯誤返回-1
#include <sygnal.h> void (*signal(int signumber, void((*func)(int))))(int);

linux提供另一個功能更強的系統(tǒng)調(diào)用sigaction:

  • 函數(shù)sigaction可以實現(xiàn)函數(shù)signal的功能,而且還提供的更加詳細的信息.

//參數(shù)signum指定要處理的信號(除SIGKILL和SIGSTOP之外)
//act和oldact都是指向信號動作結(jié)構(gòu)的指針
#include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
其中sigaction結(jié)構(gòu)的結(jié)構(gòu)體如下:
struct sigaction{ void (*sa_handler)(int); //其中sa_handler用于指向信號處理函數(shù)的地址 void (*sa_sigaction)(int, siginfo_t *, void *); //sa_sigaction是指向函數(shù)的指針, //它指向的函數(shù)有三個參數(shù),其中第二個為siginfo_t結(jié)構(gòu)體 sigset_t sa_mask; int sa_flags; //指示信號處理函數(shù)的不同選項.可以通過位運算的或運算(OR)串接不同的參數(shù)而實現(xiàn)所需的選項設置.將其賦值為0表示選用所有的默認選項 }
那么siginfo_t的結(jié)構(gòu)體如下:
struct siginfo_t{ int si_signo; //signal number int si_errno; //an errno value int si_code; //signal code pid_t si_pid; // sending process id uid_t si_uid; //real user id of sending process int si_status; //exit value or signal clock_t si_utime; //user time consumed clock_t si_stime; // system time consumed signal_t si_value; //signal value int si_int; //POSIX.1 b signal void *si_ptr; //POSIX.1b signal void *si_addr; //memory location that caused fault int si_band; //band event int si_fd; //file descriptor }
//如下是sa_flags可選標志

sa_flags 對應設置
SA_NOCLDSTOP 用于指定信號SIGCHLD,當子進程被中斷時,不產(chǎn)生此信號,當且僅當子進程結(jié)束時產(chǎn)生該信號
SA_NOCLDWAIT 當信號為SIGCHLD時,此選項可以避免子進程的僵死
SA_NODEFER 當信號處理程序正在運行時,不阻塞對于信號處理函數(shù)自身的信號功能
SA_NOMASK
SA_ONESHOT
SA_RESETHEND
SA_RESTART
SA_SIGINFO
  • 對函數(shù) sigaction 函數(shù)的簡單調(diào)用
    void sighandler(int signum);//自定義處理信號的函數(shù) //... struct sigaction act; act.sa_handler = sighandler;//指定信號處理函數(shù)的地址 sigemptyset(&act.sa_mask);//對sigaction的成員sa_mask初始化 act.sa_flags = 0;//初始化成員sa_flags if(sigaction(SIGTERM, &act, NULL)== -1){//函數(shù)調(diào)用設置對信號的處理 printf("could not register signal handler.\n"); return 1; } //...

信號集

  • 一個用戶進程常常需要對多個信號做出處理
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容