C++信号处理是指在程序运行过程中对异步事件(如错误、中断或其他条件)的响应。这些异步事件通常由操作系统发送信号给进程。C++标准库并没有直接提供信号处理的机制,但你可以使用操作系统提供的API来实现信号处理。
在Unix-like系统(如Linux)中,信号处理通常使用signal函数或sigaction函数。在Windows系统中,则使用SetConsoleCtrlHandler函数或其他相关的API。
Unix-like系统中的信号处理
使用signal函数
signal函数是处理信号的一种简单方式,但它提供的控制有限。它的原型如下:
cpp
#include <csignal>
void (*signal(int signum, void (*handler)(int)))(int);
signum参数是要处理的信号编号,handler参数是一个函数指针,指向处理该信号的函数。
例如,你可以设置一个处理SIGINT信号(通常由用户按下Ctrl+C触发)的函数:
cpp
#include <iostream>
#include <csignal>
void signalHandler(int signum) {
std::cout << "Interrupt signal (" << signum << ") received.\n";
// 清理并关闭
exit(signum);
}
int main() {
// 注册信号SIGINT的处理函数
signal(SIGINT, signalHandler);
while(1) {
std::cout << "Going to sleep..." << std::endl;
sleep(1);
}
return 0;
}
使用sigaction函数
sigaction函数提供了比signal更强大和灵活的信号处理方式。它的原型如下:
cpp
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
struct sigaction结构体定义了信号处理的行为:
cpp
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
例如,使用sigaction来设置SIGINT信号的处理函数:
cpp
#include <iostream>
#include <signal.h>
#include <unistd.h>
void signalHandler(int signum)
{
std::cout << "Interrupt signal (" << signum << ") received.\n";
exit(signum);
}
int main()
{
struct sigaction sa;
sa.sa_handler = signalHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGINT, &sa, NULL);
while(1) {
std::cout << "Going to sleep..." << std::endl;
sleep(1);
}
return 0;
}
Windows系统中的信号处理
在Windows系统中,信号处理的概念与Unix-like系统不同。Windows使用事件来处理异步操作。你可以使用SetConsoleCtrlHandler函数来设置控制台应用程序的信号处理函数。例如:
cpp
#include <iostream>
#include <windows.h>
BOOL WINAPI ConsoleHandler(DWORD dwCtrlType)
{
switch(dwCtrlType) {
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_CLOSE_EVENT:
std::cout << "Console event detected." << std::endl;
return TRUE; // 返回TRUE表示已经处理了事件
}
return FALSE; // 返回FALSE表示未处理事件,系统将执行默认操作
}
int main()
{
SetConsoleCtrlHandler(ConsoleHandler, TRUE);
while(1) {
std::cout << "Going to sleep..." << std::endl;
Sleep(1000);
}
return 0;
}
在这个例子中,ConsoleHandler函数会在接收到Ctrl+C、Ctrl+Break或关闭控制台窗口的事件时被调用。