Skip to content

C++ 信号处理

信号是操作系统向进程发送的通知,用于处理异步事件,如中断、错误等。C++ 提供了<csignal>头文件来处理信号。

1. 信号的基本概念

信号是操作系统向进程发送的异步通知,用于处理各种事件,如用户中断、段错误、非法内存访问等。

1.1 常见的信号

信号描述
SIGINT中断信号(Ctrl+C)
SIGTERM终止信号
SIGABRT异常终止信号
SIGFPE浮点异常
SIGILL非法指令
SIGSEGV段错误
SIGALRM定时器信号

2. signal 函数

signal函数用于设置信号处理函数。

2.1 基本语法

cpp
#include <csignal>

void (*signal(int sig, void (*func)(int)))(int);

示例

cpp
#include <iostream>
#include <csignal>
#include <unistd.h>

void signal_handler(int signal) {
    std::cout << "接收到信号: " << signal << std::endl;
}

int main() {
    signal(SIGINT, signal_handler);
    
    std::cout << "按 Ctrl+C 发送 SIGINT 信号" << std::endl;
    
    while (true) {
        sleep(1);
    }
    
    return 0;
}

3. 信号处理函数

3.1 处理 SIGINT 信号

cpp
#include <iostream>
#include <csignal>
#include <unistd.h>

void sigint_handler(int signal) {
    std::cout << "\n接收到 SIGINT 信号,程序即将退出" << std::endl;
    exit(0);
}

int main() {
    signal(SIGINT, sigint_handler);
    
    std::cout << "按 Ctrl+C 发送 SIGINT 信号" << std::endl;
    
    while (true) {
        sleep(1);
    }
    
    return 0;
}

3.2 处理 SIGTERM 信号

cpp
#include <iostream>
#include <csignal>
#include <unistd.h>

void sigterm_handler(int signal) {
    std::cout << "接收到 SIGTERM 信号,程序即将退出" << std::endl;
    exit(0);
}

int main() {
    signal(SIGTERM, sigterm_handler);
    
    std::cout << "使用 kill 命令发送 SIGTERM 信号" << std::endl;
    std::cout << "程序 PID: " << getpid() << std::endl;
    
    while (true) {
        sleep(1);
    }
    
    return 0;
}

3.3 处理 SIGALRM 信号

cpp
#include <iostream>
#include <csignal>
#include <unistd.h>

void sigalrm_handler(int signal) {
    std::cout << "定时器到期" << std::endl;
}

int main() {
    signal(SIGALRM, sigalrm_handler);
    
    std::cout << "设置 5 秒定时器" << std::endl;
    alarm(5);
    
    while (true) {
        sleep(1);
    }
    
    return 0;
}

4. raise 函数

raise函数用于向当前进程发送信号。

cpp
#include <iostream>
#include <csignal>

void signal_handler(int signal) {
    std::cout << "接收到信号: " << signal << std::endl;
}

int main() {
    signal(SIGINT, signal_handler);
    
    std::cout << "发送 SIGINT 信号" << std::endl;
    raise(SIGINT);
    
    return 0;
}

5. 信号处理和异常

5.1 处理 SIGFPE 信号

cpp
#include <iostream>
#include <csignal>

void sigfpe_handler(int signal) {
    std::cout << "浮点异常" << std::endl;
    exit(1);
}

int main() {
    signal(SIGFPE, sigfpe_handler);
    
    int a = 10;
    int b = 0;
    int c = a / b;
    
    std::cout << "c = " << c << std::endl;
    
    return 0;
}

5.2 处理 SIGSEGV 信号

cpp
#include <iostream>
#include <csignal>

void sigsegv_handler(int signal) {
    std::cout << "段错误" << std::endl;
    exit(1);
}

int main() {
    signal(SIGSEGV, sigsegv_handler);
    
    int* ptr = nullptr;
    *ptr = 10;
    
    return 0;
}

6. 信号处理和资源清理

6.1 使用 atexit 函数

cpp
#include <iostream>
#include <csignal>
#include <cstdlib>

void cleanup() {
    std::cout << "清理资源" << std::endl;
}

void sigint_handler(int signal) {
    std::cout << "接收到 SIGINT 信号" << std::endl;
    exit(0);
}

int main() {
    atexit(cleanup);
    signal(SIGINT, sigint_handler);
    
    std::cout << "按 Ctrl+C 发送 SIGINT 信号" << std::endl;
    
    while (true) {
        sleep(1);
    }
    
    return 0;
}

7. 示例:综合运用

现在,让我们看一个综合运用各种信号处理特性的例子:

cpp
#include <iostream>
#include <csignal>
#include <unistd.h>
#include <cstdlib>

bool running = true;

void sigint_handler(int signal) {
    std::cout << "\n接收到 SIGINT 信号" << std::endl;
    running = false;
}

void sigterm_handler(int signal) {
    std::cout << "接收到 SIGTERM 信号" << std::endl;
    running = false;
}

void sigalrm_handler(int signal) {
    std::cout << "定时器到期" << std::endl;
}

void cleanup() {
    std::cout << "清理资源" << std::endl;
}

int main() {
    atexit(cleanup);
    
    signal(SIGINT, sigint_handler);
    signal(SIGTERM, sigterm_handler);
    signal(SIGALRM, sigalrm_handler);
    
    std::cout << "程序 PID: " << getpid() << std::endl;
    std::cout << "按 Ctrl+C 发送 SIGINT 信号" << std::endl;
    std::cout << "使用 kill 命令发送 SIGTERM 信号" << std::endl;
    std::cout << "设置 5 秒定时器" << std::endl;
    
    alarm(5);
    
    int count = 0;
    while (running) {
        std::cout << "计数: " << count++ << std::endl;
        sleep(1);
    }
    
    std::cout << "程序正常退出" << std::endl;
    
    return 0;
}

小结

C++ 信号处理包括:

  1. 信号的基本概念

    • 信号是操作系统向进程发送的异步通知
    • 用于处理各种事件,如中断、错误等
  2. signal 函数

    • 用于设置信号处理函数
    • 基本语法:signal(int sig, void (*func)(int))
  3. 信号处理函数

    • 处理 SIGINT 信号(Ctrl+C)
    • 处理 SIGTERM 信号(终止信号)
    • 处理 SIGALRM 信号(定时器信号)
  4. raise 函数

    • 用于向当前进程发送信号
    • 基本语法:raise(int sig)
  5. 信号处理和异常

    • 处理 SIGFPE 信号(浮点异常)
    • 处理 SIGSEGV 信号(段错误)
  6. 信号处理和资源清理

    • 使用atexit函数注册清理函数
    • 在信号处理函数中设置标志位

关键概念:

  • 信号:操作系统向进程发送的异步通知
  • signal 函数:设置信号处理函数
  • raise 函数:向当前进程发送信号
  • SIGINT:中断信号(Ctrl+C)
  • SIGTERM:终止信号
  • SIGALRM:定时器信号
  • SIGFPE:浮点异常
  • SIGSEGV:段错误

掌握信号处理是编写健壮 C++ 程序的重要基础,在后续章节中,我们将学习 C++ 的多线程。