C++ --- 信号处理

ops/2024/11/2 12:39:50/

目录

一.什么是信号处理

二.常见信号:

 三.signal() 函数的使用:

2.signal()注意事项:

3.使用场景:

四.raise()函数的使用:

注意事项

五.自定义信号处理函数:

代码说明:


一.什么是信号处理

在 C++ 中,信号处理是处理异步事件的一种机制。信号可以由操作系统或进程自身生成,常用于通知程序某些事件的发生,例如用户中断、程序错误等。了解信号处理可以帮助开发者编写更健壮和响应快速的程序。

C++ 提供了 signal()raise() 函数来支持简单的信号处理机制。这种机制允许程序响应系统事件,比如错误(如除零)或用户中断(如按下 Ctrl+C)。通过 signal()raise(),我们可以自定义如何在特定信号被触发时执行自定义操作。

二.常见信号:

  • 信号(Signal):信号是操作系统向进程发送的异步通知,用于表示某个事件的发生。每种信号都有一个唯一的编号。
  • 信号的用途
    • 通知进程终止、挂起或继续运行。
    • 捕获错误或异常情况。
    • 处理用户输入(如中断)。

信号名称

信号编号

描述

SIGHUP

1

终端挂断(Hangup)

SIGINT

2

中断信号(通常通过按下 Ctrl+C 触发)

SIGQUIT

3

退出(Quit)

SIGILL

4

非法指令(Illegal Instruction)

SIGABRT

6

程序异常终止信号

SIGFPE

8

程序异常终止信号

SIGKILL

9

强制终止(Kill)

SIGSEGV

11

无效内存访问信号(如访问非法地址)

SIGPIPE

13

管道破裂(Broken Pipe)

SIGALRM

14

定时器到期(Alarm Clock)

SIGTERM

15

终止请求信号

SIGUSR1

10

用户定义信号 1

SIGUSR2

12

用户定义信号 2

 三.signal() 函数的使用:

1.signal()函数如何使用? 

 signal() 函数用于设置信号处理函数,以指定在特定信号到达时执行的操作。

#include <csignal>// 定义函数签名
void (*signal(int signum, void (*handler)(int)))(int);
  • 参数
    • signum:要捕获的信号编号(例如 SIGINTSIGABRT 等)。
    • handler信号处理函数的地址,表示在信号发生时需要执行的操作。可以是自定义的处理函数,或标准处理动作 SIG_DFL(默认动作)和 SIG_IGN(忽略信号)。
  • 返回值:返回先前的信号处理函数指针,或 SIG_ERR 表示错误。
#include <iostream>
#include <csignal>
#include <cstdlib>
using namespace std;// 自定义信号处理函数
void signalHandler(int signum) {cout << "收到信号 " << signum << ",程序即将终止。\n";// 清理并关闭// 终止程序  exit(signum);
}int main() {// 设置 SIGINT(Ctrl + C 中断)的信号处理函数signal(SIGINT, signalHandler);// 设置 SIGTERM(程序终止请求)的信号处理函数signal(SIGTERM, signalHandler);cout << "按 Ctrl+C 以发送 SIGINT 信号,或等待程序发出 SIGTERM 信号。\n";// 无限循环,保持程序运行while (1) {cout << "程序正在运行...\n";sleep(1); // 模拟程序工作,延迟1秒}return 0;
}

代码解析:

  • 信号处理函数 signalHandler:接受信号编号 signum 作为参数。打印信号编号并终止程序。
  • 设置信号处理:通过 signal(SIGINT, signalHandler);signal(SIGTERM, signalHandler);,我们将 signalHandler 函数设置为 SIGINTSIGTERM 信号的处理函数。
  • 程序运行:程序进入无限循环,每秒输出一次状态信息,直到接收到 SIGINTSIGTERM 信号。

2.signal()注意事项:

  • 信号处理函数的限制信号处理函数应尽可能简单,因为它会中断程序的正常执行。应避免在信号处理函数中调用诸如 mallocfreeprintf 等非线程安全的函数。
  • 跨平台性:虽然 signal() 在不同平台上可用,但信号的行为可能不同。例如,有些信号在 Windows 上可能不支持。
  • 信号默认行为:使用 SIG_DFL 恢复信号的默认处理行为,使用 SIG_IGN 忽略信号。

3.使用场景:

  1. 资源清理:当程序被外部信号中断时,可以用信号处理函数进行资源清理操作,例如关闭文件或释放内存。
  2. 控制程序流程:在长时间运行的程序中,可以通过捕获特定信号来控制程序的行为,比如暂停、重启或终止。
  3. 错误处理:捕获 SIGFPESIGSEGV 等信号可以在发生严重错误时执行特定操作,而不是让程序崩溃。

四.raise()函数的使用:

在C++中,raise() 函数是一个用来发送信号的标准库函数,定义在 <csignal> 头文件中。它的主要用途是向调用进程发送特定的信号,这可以用来控制程序的行为,比如终止程序、暂停程序等。

#include <csignal>int raise(int signum);
  • 参数signum:要发送的信号编号。
  • 返回值:成功发送信号返回 0,如果信号无法被发送,返回非零值。
#include <iostream>
#include <csignal>
#include <cstdlib>
#include <unistd.h>
using namespace std;// 信号处理函数
void signalHandler(int signum) {cout << "Caught signal: " << signum << endl;// 退出程序exit(signum);
}int main() {// 注册信号处理函数signal(SIGINT, signalHandler);signal(SIGTERM, signalHandler);cout << "Process ID: " << getpid() << endl;cout << "Press Ctrl+C to send SIGINT signal." << endl;// 无限循环,等待信号while (true) {sleep(1); // 暂停一秒}return 0;
}

注意事项

  • 使用 raise() 发送信号时,通常不会产生立即的影响,因为信号的处理是异步的。信号处理程序会在程序的当前执行上下文中被调用。
  • 在多线程程序中,信号会影响整个进程,而不是单个线程。

raise() 函数在调试和程序控制中非常有用,可以用来模拟信号的发送,帮助开发者更好地理解信号的处理。

五.自定义信号处理函数:

自定义信号处理函数可以用来记录日志、重启程序等高级功能。以下是另一个示例代码,处理除零错误(SIGFPE)和无效内存访问(SIGSEGV)信号。

#include <iostream>
#include <csignal>
#include <cstdlib>void signalHandler(int signum) {if (signum == SIGFPE) {std::cerr << "收到 SIGFPE(除零错误),请检查计算逻辑。\n";} else if (signum == SIGSEGV) {std::cerr << "收到 SIGSEGV(无效内存访问),请检查指针。\n";} else {std::cerr << "收到未知信号,编号:" << signum << "\n";}exit(signum); // 终止程序
}int main() {// 注册 SIGFPE 和 SIGSEGV 信号signal(SIGFPE, signalHandler);signal(SIGSEGV, signalHandler);std::cout << "除零错误测试:5 / 0\n";int result = 5 / 0; // 触发 SIGFPEreturn 0;
}
代码说明:
  1. 捕获 SIGFPE 和 SIGSEGV 信号:注册 SIGFPESIGSEGV,通过 signalHandler 处理除零错误和无效内存访问。
  2. 触发信号:当 5 / 0 执行时,产生 SIGFPE,程序进入 signalHandler

http://www.ppmy.cn/ops/130425.html

相关文章

Linux高阶——1027—守护进程

1、守护进程的基本流程 1、父进程创建子进程&#xff0c;父进程退出 守护进程是孤儿进程&#xff0c;但是是工程师人为创建的孤儿进程&#xff0c;低开销模式运行&#xff0c;对系统没有压力 2、子进程&#xff08;守护进程&#xff09;脱离控制终端&#xff0c;创建新会话 …

OpenAI推出搜索GPT,进军搜索引擎领域

OpenAI 推出了一项新功能——Search GPT&#xff0c;为 ChatGPT 引入实时网络搜索功能&#xff0c;使其站上与 Google 和 Bing 等搜索巨头竞争的舞台。 OpenAI 产品的重大变化&#xff0c;Search GPT 承诺提供快捷、实时的答案&#xff0c;并附上可靠来源的链接。 ChatGPT 一直…

「C/C++」C++11 之 std::pair单元存储的途径

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

Spring Boot JPA中的Page组件详解

1. 简介 在开发企业级应用时&#xff0c;分页查询是一个非常常见的需求。Spring Boot JPA提供了强大的分页功能&#xff0c;通过Page接口和Pageable接口&#xff0c;我们可以轻松实现灵活的分页查询。本文将详细介绍Page组件的使用方法及其核心特性。 2. 核心概念 2.1 Page接…

《化学试剂》

《化学试剂》主要报道化学试剂、精细化学品、专用化学品及相关领域的最新研究进展、理论知识、科研成果、技术经验、新产品的合成、分离、提纯以及各种分析测试技术、分析仪器、行业动态等&#xff0c;及时反映国内外的发展水平。 《化学试剂》投稿指南 目前《化学试剂》期刊已…

sklearn机器学习实战

1.PCA降维 不是每个数据特征对分析的问题都有用。即使有用&#xff0c;对问题的重要程度也不一样。而我们需要过滤和筛选一些特征&#xff0c;去除冗余。 数据降维是指采取某种映射方法&#xff0c;把高维空间中可能包含冗余信息和噪声的数据点映射到低维空间&#xff0c;在低…

Javaweb 实验4 xml

我发现了有些人喜欢静静看博客不聊天呐&#xff0c; 但是ta会点赞。 这样的人呢帅气低调有内涵&#xff0c; 美丽大方很优雅。 说的就是你&#xff0c; 不用再怀疑哦 实验四 XML 目的&#xff1a; 安装和使用XML的开发环境认识XML的不同类型掌握XML文档的基本语法了解D…

【生物学&水族馆】观赏淡水鱼检测系统源码&数据集全套:改进yolo11-dysample

改进yolo11-SEAMHead等200全套创新点大全&#xff1a;观赏淡水鱼检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.11.01 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系统图片或者…