標籤:
訊號處理是linux程式的一個特色。用訊號處理來類比作業系統的中斷功能。要想使用訊號處理功能,你要做的就是填寫一個訊號處理函數即可。
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <stdlib.h> 4 #include <signal.h> 5 6 int flag = 1; 7 8 void func(int sig) 9 { 10 printf("I get a signal!\n"); 11 flag = 0; 12 } 13 14 int main() 15 { 16 signal(SIGINT, func); 17 printf("pid:%ld\n",(long)getpid()); 18 19 while(flag) 20 pause(); 21 22 return 0; 23 }
執行:
#gcc sig.c -o sig #./sig 在另一終端: #kill -INT 333//333是程式列印出的進程號
要對一個訊號進行處理,就需要給出此訊號發生時系統所調用的處理函數。可以對一個特定的訊號(除去SIGKILL和SIGSTOP訊號)註冊相應的處理函數。註冊某個訊號的處理函數後,當進程接收到此訊號時,無論進程處於何種狀態,就會停下當前的任務去執行此訊號的處理函數。
1. 註冊訊號函數
#include<signal.h> void(*signal(int signumber,void ((*func)(int))(int)
signumber表示訊號處理函數對應的訊號。func是一個函數指標。此函數有一整型參數,並返回void型。其實func還可以取其他定值如:SIG_IGN,SIG_DFL。SIG_IGN表示:忽略signumber所指出的訊號。SIG_DFL表示表示調用系統預設的處理函數。signal函數的傳回值類型同參數func,是一個指向某個傳回值為空白並帶有一個整型參數的函數指標。其正確傳回值應為上次該訊號的處理函數。錯誤返回SIG_ERR。
signal樣本如下:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <stdlib.h> 4 #include <signal.h> 5 6 void func(int sig) 7 { 8 printf("I get asignal!\n"); 9 } 10 11 int main() 12 { 13 charbuffer[100]; 14 15 if(signal(SIGINT, func) == SIG_ERR) 16 { 17 printf("signalerror exit now\n"); 18 exit(0); 19 } 20 printf("pid:%ld\n",(long)getpid()); 21 22 for(;;) 23 { 24 fgets(buffer,sizeof(buffer),stdin); 25 printf("bufferis:%s\n",buffer); 26 } 27 return 0; 28 }
通常情況下一個使用者進程需要處理多個訊號。可以在一個程式中註冊多個訊號處理函數。一個訊號可以對應一個處理函數,同時多個訊號可以對應一個處理函數。對於SIGINT訊號 我們可以用ctrl+c或ctrl+z來中斷進程,來執行SIGINT註冊的函數。
2. 進階訊號處理
在linux系統提供了一個功能更強的系統調用。
#include <signal.h> int sigaction(int signumbet,const structsigaction *act,struct sigaction *oldact)
此函數除能註冊訊號函數外還提供了更加詳細的資訊,確切瞭解進程接收到訊號,發生的具體細節。struct sigaction的定義如下:
struct sigaction { void(*sa_handler)(int); void(*sa_sigaction)(int,siginfo_t *,void *); sigset_tsa_mask; intsa_flags; }
sa_flags的取值如下表,取0表示選用所有預設選項。
SA_NOCLDSTOP:用於表示訊號SIGCHLD,當子進程被中斷時,不產生此訊號,若且唯若子進程結束時產生此訊號。
SA_NOCLDWATI:當訊號為SIGCHLD,時可避免子進程僵死。
SA_NODEFER:當訊號處理函數進行中時,不堵塞對於訊號處理函數自身訊號功能。
SA_NOMASK:同SA_NODEFER
SA_ONESHOT:當使用者註冊的訊號處理函數被執行過一次後,該訊號的處理函數被設為系統預設的處理函數。
SA_RESETHAND:同SA_ONESHOT
SA_RESTART:是本來不能重新於啟動並執行系統調用自動重新運行。
SA_SIGINFO:表明訊號處理函數是由SA_SIGACTION指定的,而不是由SA_HANDLER指定的,它將顯示更多的訊號處理函數資訊。
其實sinaction完全可以替換signal函數:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <stdlib.h> 4 #include <signal.h> 5 6 void func(int sig) 7 { 8 printf("I get a signal!\n"); 9 } 10 11 int main() 12 { 13 char buffer[100]; 14 15 struct sigaction act; 16 act.sa_handler=func; 17 sigemptyset(&act.sa_mask); 18 act.sa_flags = 0; 19 20 if(sigaction(SIGINT,&act, NULL) == -1) 21 { 22 printf("sigaction error exit now\n"); 23 exit(0); 24 } 25 26 printf("pid:%ld\n",(long)getpid()); 27 28 for(;;) 29 { 30 fgets(buffer,sizeof(buffer),stdin); 31 printf("buffer is:%s\n",buffer); 32 } 33 34 return 0; 35 }
linux之C編程學習——訊號處理