C++信号处理
注册处理信号
头文件signal.h。
param1:信号的类型。
param2:处理信号事件的回调函数。
void signal(int, void (*callback)(int));
注册了某个信号后,当系统收到这个信号,就会调用回调函数。
这种注册是一次性。意思是,系统调用了一次回调函数后,当这个信号再次触发,系统将不会调用这个回调函数,而是使用默认的处理方法。
示例:
void callback(int tag){
cout << "recive signal : " << tag << endl;
}
int main()
{
signal(SIGINT, callback);
while (1){
Sleep(500);
raise(SIGINT);
}
return 0;
}
效果:控制面板输出一次后,程序自动关闭。
这种注册是不可重复的。意思是,即使你连续重复注册某个信号,实际效果与注册一次相同。
示例:
void callback(int tag){
cout << "recive signal : " << tag << endl;
}
int main()
{
signal(SIGINT, callback);
signal(SIGINT, callback);
signal(SIGINT, callback);
while (1){
Sleep(500);
raise(SIGINT);
}
return 0;
}
效果:控制面板输出一次后,程序自动关闭。
主动发送信号
param1:信号的类型。
void raise(int)
发送的信号类型必须是系统给出的,不然,运行程序会报错。
示例:
//main()中
raise(1);
报错:未知的信号或错误。
系统给出的信号类型,在signal.h头文件中查看。
类型 | 值 | 描述 |
---|---|---|
#define SIGINT | 2 | 中断 |
#define SIGILL | 4 | 非法指令-无效函数镜像 |
#define SIGFPE | 8 | 错误的算术运算,比如除以零或导致溢出的操作 |
#define SIGSEGV | 11 | 非法访问内存 |
#define SIGTERM | 15 | 通过kill发送到本进程的终止信号 |
#define SIGBREAK | 21 | Ctrl-Break sequence |
#define SIGABRT | 22 | 程序的异常终止,如调用 abort。 |
#define SIGABRT_COMPAT | 6 | SIGABRT 兼容其它平台, 类似于 SIGABRT |
连续收发同一信号示例
可以看到,发送周期为500毫秒,处理函数周期为1000毫秒。而控制台打印是连续的,所以,raise()是阻塞的。
void callback(int tag){
cout << "recive signal : " << tag << endl;
Sleep(1000);
signal(SIGINT, callback);
}
int main()
{
signal(SIGINT, callback);
while (1){
Sleep(500);
raise(SIGINT);
cout << "send signal : " << SIGINT << endl;
}
return 0;
}
输出结果,打印连续。
一个疑问
写了个示例,第一次按Ctrl+C,控制台没输出。通过打断点,发现根本没进回调函数。第二次按Ctrl+C,弹出警告窗口。
期望的效果是按下Ctrl+C,控制台有打印。难道这个示例在linux上才能有效果?
当前环境:win7 + VS2015。
代码:
void callback(int tag){
cout << "recive signal : " << tag << endl;
}
int main()
{
signal(SIGINT, callback);
while (1){
Sleep(500);
}
return 0;
}