信号处理函数是进程接收到信号后要执行的函数,该函数应该尽量简洁。只改变一个标志位。
注意事项:
1.如果处理程序需要用到一个全局变量,用volatile关键字进行提醒编译器不要优化,防让每次读取数据都保证是从数据所在的地址内存得到的。
2.如果在信号处理函数中调用函数,函数必须是可以重入的,保证在信号处理函数执行期间不会有信号到达进程,Linux系统有和你多不可以重入函数,比如malloc,gethostbyname等等。
长跳转操作是从信号处理函数直接跳转到函数体外制定的代码位置继续运行,很多情况长跳转可以减少代码的复杂度。两个函数sigsetjmp和siglongjmp,在成功调用sigsetjmp
后,sigsetjmp语句所在位置就是跳转点,这个位置指针被保存到sigsetjmp的第一个参数里面,siglongjmp用于跳转到指定的跳转点。位于setjmp.h里面。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<wait.h>
#include<errno.h>
#include<signal.h>
#include <setjmp.h>
#include<sys/types.h>
#include<fcntl.h>
#include<sys/stat.h>
static sigjmp_buf jmpbuf;//静态全局变量,保存跳转点
static volatile int IsOK;//防止优化,因为中断处理函数和主函数都用到这个函数
void handle_sigint(int signo)
{
if(!IsOK) return;/*如果在没有调用sigsetjmp函数情况下收到信号,不做任何处理*/
printf("receive signal %d.\n",signo);/*输出相关信息*/
IsOK = 0;/*复位Isok,确保下一次收到信号,主函数已经调用了sigsetjmp*/
siglongjmp(jmpbuf,1);/*长跳转到jmpbuf*/
}
int main()
{
int n;
signal(SIGINT,handle_sigint);
n = sigsetjmp(jmpbuf,1);//保存跳转点
if(n == 0)
printf("first call sigsetjmp\n");
else/*从信号处理函数跳转过来时,sigsetjmp将返回非0*/
{
printf("call sigsetjmp after siglongjmp\n");
return;
}
IsOK = 1;
for(;;)
{
pause();
}
return 0;
}