C语言信号处理
一个外部的异步事件或者信号,能够引起程序提前结束。常见的时间有:中断(在Linux、UNIX或者Windows系统中键入组合键Ctrl+c,在OS X系统中键入组合键command+c)和来自操作系统的终端命令。
信号处理函数库(signal.h)提供了基于函数signal的捕获异常事件能力。
函数signal接收两个实参——整型的信号编号和指向相应的信号处理函数的指针。信号可以通过函数raise来产生,该函数接收一个整型的信号编号作为实参。
下表总结了定义在头文件<signal.h>中的标准信号。
信号 | 说明 |
---|---|
SIGABRT | 程序的异常终止(如对函数abort的调用) |
SIGFPE | 一个错误的算术运算操作。如除数为零或者运算结果溢出 |
SIGILL | 检测到一个非法指令 |
SIGINT | 收到一个交互提示信号(Ctrl+c或command+c) |
SIGSEGV | 试图访问未分配给程序的存储空间 |
SIGTERM | 发给程序的终止请求 |
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<time.h>
void signalHandler(int signalValue){
printf("\nInterrupt signal (%d) received.\nDo you wish to continue (1 = yes or 0 = no)?",signalValue);
int response;
scanf("%d",&response);
while(response != 0 && response != 1){
printf("(1 = yes or 0 = no)?");
scanf("%d",&response);
}
if(response == 1){
signal(SIGINT, signalHandler);
}
else{
exit(EXIT_SUCCESS);
}
}
int main(){
signal(SIGINT, signalHandler);
srand(time(NULL));
for(int i = 1; i <= 100; ++i){
int x = 1 + rand() %50;
if(x == 25){
raise(SIGINT);
}
printf("%4d",i);
if(i % 10 == 0){
printf("\n");
}
}
}
上面这个程序,使用了函数signal来捕获一个信号SIGINT。
signal(SIGINT, signalHandler);
这个语句用SIGINT和指向函数signalHandler的指针来调用函数signal。当出现类型为SIGINT的信号时,控制将传递给函数signalHandler。该函数打印出一条信息并提示用户选择是否继续程序的正常执行。如果用户想继续执行程序,则通过再次调用函数signal重新初始化信号处理函数,并将控制返回到原先程序检测到信号的位置。
在程序中,函数raise被用来模拟一个SIGINT信号。程序首先产生一个大小在1~50之间的随机数,若此随机数时25,则调用函数raise来产生一个SIGINT。通常SIGINT是在程序之外产生的。
例如,当程序在Linux/UNIX或Windows系统上运行时,键入组合键Ctrl+c将产生一个能结束程序运行的SIGINT。
本程序中的信号处理功能就是要捕获这样的交互信号以放在程序被恶意终止。