信号处理是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 }