C++信号处理

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或关闭控制台窗口的事件时被调用。

相关推荐
漫漫进阶路1 小时前
VS C++ 配置OPENCV环境
开发语言·c++·opencv
hefaxiang5 小时前
【C++】函数重载
开发语言·c++·算法
花生树什么树5 小时前
下载Visual Studio Community 2019
c++·visual studio·vs2019·community
exp_add35 小时前
Codeforces Round 1000 (Div. 2) A-C
c++·算法
练小杰6 小时前
Linux系统 C/C++编程基础——基于Qt的图形用户界面编程
linux·c语言·c++·经验分享·qt·学习·编辑器
勤又氪猿6 小时前
【问题】Qt c++ 界面 lineEdit、comboBox、tableWidget.... SIGSEGV错误
开发语言·c++·qt
Ciderw6 小时前
Go中的三种锁
开发语言·c++·后端·golang·互斥锁·
人才程序员8 小时前
【C++拓展】vs2022使用SQlite3
c语言·开发语言·数据库·c++·qt·ui·sqlite
OKkankan8 小时前
实现二叉树_堆
c语言·数据结构·c++·算法
Ciderw9 小时前
MySQL为什么使用B+树?B+树和B树的区别
c++·后端·b树·mysql·面试·golang·b+树