当前位置: 首页 > news >正文

信号(Signal)** 是一种进程间异步通信机制,用于通知进程发生发生了某种事件(如错误、用户中断等)

在 Unix/Linux 系统中,信号(Signal) 是一种进程间异步通信机制,用于通知进程发生发生了某种事件(如错误、用户中断等)。信号可以由内核、其他进程或进程自身发送,接收信号的进程会中断当前操作,转而去执行预设的处理函数(或默认行为)。

信号的核心特性

  1. 异步性:信号的产生和传递是不确定的,进程无需主动等待,会在信号到达时被打断。
  2. 事件驱动:每种信号对应特定事件(如 SIGINT 对应 Ctrl+C 中断,SIGSEGV 对应段错误)。
  3. 预设处理方式:每个信号有默认处理行为(终止、忽略、暂停等),也可自定义处理函数。

常见信号及其含义

信号名编号含义及触发场景默认行为
SIGINT2用户按下 Ctrl+C 中断进程终止进程
SIGTERM15请求进程终止(kill 命令默认发送)终止进程
SIGKILL9强制终止进程(不可捕获/忽略)终止进程
SIGSEGV11段错误(访问无效内存地址)终止进程并生成核心转储
SIGPIPE13向已关闭的管道写入数据终止进程
SIGALRM14定时器超时(alarm() 函数触发)终止进程
SIGCHLD17子进程终止或状态改变忽略

信号处理函数

进程可以通过 signal()sigaction() 函数自定义信号的处理方式(信号捕获)。

1. signal() 函数(简单但功能有限)
#include <signal.h>// 信号处理函数原型:参数为信号编号
void (*signal(int signum, void (*handler)(int)))(int);
  • signum:要处理的信号(如 SIGINT)。
  • handler:处理函数指针,或特殊值:
    • SIG_IGN:忽略该信号。
    • SIG_DFL:恢复默认行为。
2. sigaction() 函数(更灵活,推荐使用)
#include <signal.h>int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);// 信号处理结构体
struct sigaction {void (*sa_handler)(int);  // 处理函数sigset_t sa_mask;         // 处理信号时阻塞的其他信号int sa_flags;             // 标志(如 SA_RESTART 重启被中断的系统调用)
};

示例代码:捕获 SIGINT 信号

#include <stdio.h>
#include <signal.h>
#include <unistd.h>// 自定义信号处理函数
void handle_sigint(int signum) {printf("\n收到 SIGINT 信号(Ctrl+C),程序不会退出!\n");
}int main() {// 注册 SIGINT 信号的处理函数struct sigaction sa;sa.sa_handler = handle_sigint;  // 设置处理函数sigemptyset(&sa.sa_mask);       // 不阻塞其他信号sa.sa_flags = 0;                // 默认标志if (sigaction(SIGINT, &sa, NULL) == -1) {perror("sigaction failed");return 1;}printf("程序运行中,按 Ctrl+C 测试信号处理...\n");while (1) {sleep(1);  // 无限循环等待信号}return 0;
}

运行效果
按下 Ctrl+C 后,程序不会终止,而是执行 handle_sigint 函数并继续运行(默认行为被覆盖)。

信号发送与处理流程

  1. 信号发送
    可通过 kill()pthread_kill() 向进程发送信号:

    #include <sys/types.h>
    #include <signal.h>// 向进程 pid 发送 signum 信号
    int kill(pid_t pid, int signum);
    

    例如:kill(12345, SIGTERM) 向 PID 为 12345 的进程发送终止请求。

  2. 信号处理流程

    • 信号产生后,内核将其标记到目标进程的信号掩码中。
    • 进程从内核态返回用户态时,检查是否有未处理的信号。
    • 若有,暂停当前执行,转而去执行该信号的处理函数。
    • 处理完成后,回到被中断的位置继续执行。

注意事项

  1. 不可靠信号与可靠信号

    • 早期 Unix 信号(如 SIGINTSIGTERM)为不可靠信号(编号 < 32),可能丢失且不支持排队。
    • POSIX 扩展的实时信号(SIGRTMINSIGRTMAX)为可靠信号,支持排队和携带附加数据。
  2. 信号安全函数
    信号处理函数中应使用异步信号安全函数(如 write_exit),避免调用 printfmalloc 等非安全函数(可能导致死锁)。

  3. SIGKILLSIGSTOP
    这两个信号不可捕获、不可忽略、不可自定义处理,用于强制终止或暂停进程(系统级控制)。

  4. 信号屏蔽
    可通过 sigprocmask() 暂时屏蔽某些信号,防止其在关键操作(如数据更新)中打断进程。

应用场景

  • 进程终止控制(如 kill 命令发送 SIGTERM)。
  • 异常处理(如捕获 SIGSEGV 记录崩溃信息)。
  • 用户交互(如 Ctrl+C 中断程序)。
  • 进程间通知(如子进程结束后通过 SIGCHLD 通知父进程)。

信号是 Unix 系统中最基础的异步通信机制,广泛用于处理突发事件和进程控制,但需注意其异步性带来的复杂性(如数据一致性问题)。

http://www.dtcms.com/a/327367.html

相关文章:

  • 疯狂星期四文案网第37天运营日记
  • Apache POI中通过WorkBook写入图片后出现导出PDF文件时在不同页重复写入该图片问题,如何在通过sheet获取绘图对象清除该图片
  • 通过限制对象的内存分配位置来实现特定的设计目标
  • 【数据结构入门】堆
  • powerbi本地报表发布到web,以得到分享链接
  • C99中的变长数组(VLA)
  • 什么是 Spring MVC?
  • 中扬立库与西门子深化技术协同 共绘智能仓储创新蓝图
  • clean install 和 clean package 的区别
  • JVM学习笔记-----图解方法执行流程
  • 百胜软件×华为云联合赋能,“超级国民品牌”海澜之家新零售加速前行
  • 【力扣494】目标和
  • 【软考中级网络工程师】知识点之 IP QoS 技术
  • JVM宝典
  • 面试八股之从Java到JVM层面深入解析ReentrantLock实现原理
  • 力扣top100(day01-05)--矩阵
  • 开放原子开源生态大会:麒麟信安加入openEuler社区AI联合工作组,聚焦操作系统开源实践与行业赋能
  • Linux下的软件编程——文件IO
  • Openlayers基础教程|从前端框架到GIS开发系列课程(24)openlayers结合canva绘制矩形绘制线
  • 循环神经网络
  • THCV215一种高速视频数据收发器,采用低电压差分信号(LVDS)技术支持高速串行数据传输,支持1080p/60Hz高分辨率传输
  • 【[特殊字符][特殊字符] 协变与逆变:用“动物收容所”讲清楚 PHP 类型的“灵活继承”】
  • Gradle(二)Gradle的优势、项目结构介绍
  • 电商双11美妆数据分析(一)
  • Honeywell霍尼韦尔A205压力传感器HC41H106P060169419G固瑞克117764美国制造
  • Rust 项目编译故障排查:从 ‘onnxruntime‘ 链接失败到 ‘#![feature]‘ 工具链不兼容错误
  • KAQG:一种用于生成难度可控问题的知识图谱的增强的RAG系统(论文大白话)
  • 2025AI行业升级生态战:谁在“种树”?谁在“造林”?
  • 02-Ansible 基本使用
  • Visual Studio中VC++目录、C/C++和链接器配置的区别与最佳实践