信号是由操作系统传给进程的中断,会提早终止一个程序。在 LINUX 或 Windows 系统上,可以通过按 Ctrl+C 产生中断。有些信号不能被程序捕获,但是下表所列信号可以在程序中捕获,并可以基于信号采取适当的动作。这些信号是定义在 C++ 头文件 <csignal> 中。

使用 signal() 函数捕获 SIGINT 信号, 函数的定义signal(registered signal, signal handler)接收两个参数:第一个参数代表了信号的编号;第二个参数是一个指向信号处理函数的指针。不管您想在程序中捕获什么信号,您都必须使用 signal 函数来注册信号,并将其与信号处理函数关联。

使用函数 raise() 生成信号,该函数定义int raise (signal sig)带有一个整数信号编号作为参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <cstdio>
#include <csignal>
#include <cstdlib>

#if defined(__linux__)
#include <unistd.h>
#elif defined(_WIN32)
#include <Windows.h>
// 可恶!VC中的Sleep函数头字母S是大写的,而且单位是毫秒
#define sleep(n) Sleep(n*1000)
#endif

void signalHandler(int sign) {
	std::printf("interrupt signal (%d) received, abort.\n", sign);
	exit(sign);
}

int main() {
	// 注册信号
	signal(SIGTERM, signalHandler);
	signal(SIGINT, signalHandler);
	// 业务循环
	while (true) {
		std::printf("Going to sleep 1 second..\n");
		sleep(1);
	}
}

可捕获的信号类型如下:

1
2
3
4
5
6
SIGABRT	程序的异常终止,如调用 abort。
SIGFPE	错误的算术运算,比如除以零或导致溢出的操作。
SIGILL	检测非法指令。
SIGINT	程序终止(interrupt)信号。普通的kill操作。
SIGSEGV	非法访问内存。
SIGTERM	发送到程序的终止请求。前台执行时Ctrl+C操作。

编译执行下试试,尝试按了Ctrl+C按键和使用kill命令,进程均正常接收到信号退出。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
raveh@DESKTOP-MBGF84O:~/work/cpp$ g++ Day05.cpp
raveh@DESKTOP-MBGF84O:~/work/cpp$ ./a.out
Going to sleep 1 second..
Going to sleep 1 second..
Going to sleep 1 second..
^Cinterrupt signal (2) received, abort.
raveh@DESKTOP-MBGF84O:~/work/cpp$
raveh@DESKTOP-MBGF84O:~/work/cpp$
raveh@DESKTOP-MBGF84O:~/work/cpp$
raveh@DESKTOP-MBGF84O:~/work/cpp$ ./a.out
Going to sleep 1 second..
Going to sleep 1 second..
Going to sleep 1 second..
interrupt signal (15) received, abort.

# windows下调试
Going to sleep 1 second..
Going to sleep 1 second..
Going to sleep 1 second..
interrupt signal (2) received, abort.

D:\workspace\cpp\VSProjects\hiCPP\bin\Win32\Debug\hiCPP.exe (进程 2508)已退出,代码为 2。
按任意键关闭此窗口. . .