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

linux中信号解析

1. 信号的基本概念

1.1 什么是信号?

信号是一种软件中断,用于通知进程发生了某个事件。信号可以由内核、另一个进程或进程自身发送。信号通常用于以下目的:

  • 通知错误:如非法内存访问(SIGSEGV)。
  • 控制进程:如终止进程(SIGTERM)、暂停进程(SIGSTOP)。
  • 用户交互:如用户按下Ctrl+C发送SIGINT信号。

1.2 信号的分类

  • 标准信号:传统的信号,如SIGINTSIGTERMSIGSEGV等。
  • 实时信号(可靠信号):信号编号从SIGRTMINSIGRTMAX,可以排队处理,不会丢失。

 

2. 常见的信号

以下是一些常见的Linux信号及其含义:

 

 

3. 信号的处理方式

每个信号都有其默认的处理方式,进程可以通过以下方式改变信号的处理方式:

3.1 默认处理方式

  • Terminate:终止进程。
  • Ignore:忽略信号。
  • Core Dump:生成核心转储文件并终止进程。
  • Stop:停止进程。
  • Continue:继续进程。

3.2 使用 signal 函数

signal函数用于设置信号的处理方式,但其行为在不同系统上可能有所不同,且不具备可重入性

 

 

参数解释:

  • signum

    • 含义:指定要处理的信号类型。例如,SIGINT(信号值为2)表示中断信号,通常由用户按下 Ctrl+C 触发。
    • 取值范围:通常使用标准信号(如 SIGINTSIGTERM 等)或实时信号(SIGRTMIN 到 SIGRTMAX)。
  • sighandler_t handler

    • 含义:指定信号的处理函数。当信号 signum 发生时,将调用该函数。
    • 类型sighandler_t 是一个函数指针,指向一个返回类型为 void 且接受一个 int 参数的函数。该参数为触发信号的信号编号。
    • 特殊值
      • SIG_IGN:忽略该信号。
      • SIG_DFL:恢复信号的默认处理方式。

 例子:

#include <signal.h>
#include <stdio.h>void handler(int sig) {printf("Received signal: %d\n", sig);
}int main() {if (signal(SIGINT, handler) == SIG_ERR) {perror("signal");return 1;}while (1) {printf("Waiting for signal...\n");sleep(1);}return 0;
}

 

3.3 使用 sigaction 函数

sigaction提供了更可靠和可重入的信号处理方式,推荐使用。

参数解释:

  • signum

    • 含义:和上面一致
  • const struct sigaction *act

    • 含义:指向一个 struct sigaction 结构体,该结构体指定了新的信号处理方式。
    • 结构体成员
      • sa_handler:类似于 signal 函数中的 handler,指定信号处理函数或 SIG_IGNSIG_DFL
      • sa_mask:一个信号集,指定在执行信号处理函数期间要屏蔽的额外信号。
      • sa_flags:一组标志,用于控制信号处理的行为。例如,SA_RESTART 表示在信号处理后重启被中断的系统调用。
  • struct sigaction *oldact

    • 含义:指向一个 struct sigaction 结构体,用于保存之前的信号处理方式。如果不需要保存,可以传递 NULL

 

例子:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>void handler(int sig) {printf("Received signal: %d\n", sig);
}int main() {struct sigaction sa;sa.sa_handler = handler;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;if (sigaction(SIGINT, &sa, NULL) == -1) {perror("sigaction");return 1;}while (1) {printf("Waiting for signal...\n");sleep(1);}return 0;
}

4. 信号屏蔽与等待

4.1 信号屏蔽

使用sigprocmask函数可以临时屏蔽某些信号,直到主程序完成关键操作。

参数解释:

  • how

    • 含义:指定如何修改当前的信号屏蔽集。
      • SIG_BLOCK:将 set 中的信号添加到当前信号屏蔽集中。
      • SIG_UNBLOCK:从当前信号屏蔽集中移除 set 中的信号。
      • SIG_SETMASK:将当前信号屏蔽集设置为 set
  • const sigset_t *set

    • 含义:指向一个信号集,指定要修改的信号。
    • 特殊值:如果 set 为 NULL,则 how 参数被忽略,oldset 将包含当前的信号屏蔽集。
  • sigset_t *oldset

    • 含义:指向一个信号集,用于保存之前的信号屏蔽集。如果不需要保存,可以传递 NULL

 

例子:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>void handler(int sig) {printf("Received signal: %d\n", sig);
}int main() {sigset_t mask, oldmask;struct sigaction sa;sa.sa_handler = handler;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;if (sigaction(SIGINT, &sa, NULL) == -1) {perror("sigaction");return 1;}// 初始化信号集并添加SIGINT到屏蔽集中sigemptyset(&mask);sigaddset(&mask, SIGINT);if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) {perror("sigprocmask");return 1;}// 执行关键操作printf("关键操作开始,SIGINT被屏蔽\n");sleep(5);printf("关键操作结束,恢复SIGINT\n");// 恢复之前的信号屏蔽if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {perror("sigprocmask");return 1;}while (1) {printf("Waiting for signal...\n");sleep(1);}return 0;
}

4.2 信号等待

使用sigsuspend函数可以等待特定信号的发生。

 

参数解释:

  • const sigset_t *mask
    • 含义:指向一个信号集,指定在等待信号期间要临时设置的信号屏蔽集。
    • 行为:该函数会原子性地将当前的信号屏蔽集替换为 mask,然后挂起进程,直到接收到一个未屏蔽的信号。接收到信号后,进程的信号屏蔽集会恢复到原来的状态。

 例子:

#include <signal.h>
#include <stdio.h>
#include <unistd.h>void handler(int sig) {printf("Received signal: %d\n", sig);
}int main() {sigset_t mask, oldmask;struct sigaction sa;sa.sa_handler = handler;sigemptyset(&sa.sa_mask);sa.sa_flags = 0;if (sigaction(SIGINT, &sa, NULL) == -1) {perror("sigaction");return 1;}// 初始化信号集并添加SIGINT到屏蔽集中sigemptyset(&mask);sigaddset(&mask, SIGINT);if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) {perror("sigprocmask");return 1;}// 等待信号printf("等待信号...\n");sigsuspend(&oldmask);// 恢复信号屏蔽if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {perror("sigprocmask");return 1;}return 0;
}

相关文章:

  • 北京市建设委员会和城乡建设网站百度网盘app官网
  • 建筑安全员证查询官网排名优化课程
  • 黄石做网站的seo关键词优化软件
  • 网站建设的总体设计概图新冠疫情最新情况
  • 微信打字赚钱平台30元广告优化师发展前景
  • 焦作做网站公司数据交换平台
  • Unity3D仿星露谷物语开发70之背景音乐
  • Docker 数据持久化完全指南:Volume、Bind Mount 与匿名卷
  • 多网卡与网关配置关系详解:是否能共用、如何分配、如何避免冲突
  • Android 开发问题:Wrong argument type for formatting argument ‘#2‘ in info_message
  • 有AI后,还用学编程吗?
  • C++(异常处理)
  • 电影交流平台小程序完整项目
  • 鸿蒙OH南向开发 轻量系统内核(LiteOS-M)【异常调测】
  • linux操作系统的软件架构分析
  • 左神算法之双集合平均值优化操作的最大次数
  • 【Linux】高级IO
  • MySQL:深入总结锁机制
  • 机器学习×第十四卷:集成学习中篇——她从每次错误中修正自己
  • Java实现简易即时通讯系统
  • Linux离线搭建Jenkins
  • C++【生存游戏】开发:荒岛往事 第一期
  • GLib库介绍与linux下应用
  • 基于元学习的回归预测模型如何设计?
  • ubuntu20.04安装多版本python时,如何使用sudo python3.10
  • Linux系统---Nginx配置nginx状态统计