讲师中心 微信公众号
AI工具推荐 视频效率加速

【Linux】进程信号的发送和保存

浅瑶小哥_7879

浅瑶小哥_7879

发布时间:2025-06-21 13:04:01

|

514人浏览过

|

来源于php中文网

原创

一、信号发送

  1. 信号动作

通过指令man -7 signal查看信号的手册,可以找到普通信号发出后对应的操作、信号编号和详细描述信息。

【Linux】进程信号的发送和保存

  1. 信号发送的本质

普通信号的发送本质上是将信号写入进程的PCB结构体中的位图(pending位图)。这个位图对应着1到31号的普通信号,收到信号后将对应比特位置为1,表示信号已收到,然后PCB执行相应的工作。值得注意的是,如果连续发送普通信号,进程只会处理最后一次的信号,因为每次写入都是覆盖式的。

实时信号与普通信号类似,但它们使用的是结构体而非位图,信号被组织在队列中,遵循先入先出的规则。如果连续发送实时信号,进程会依次处理队列中的所有信号。

  1. Core Dump

在《进程控制》一文中,我们解释了wait函数的status参数,其中第7位是core dump标志。程序在运行过程中发生崩溃(如段错误、除零错误等)时,Core dump会记录程序崩溃瞬间的内存状态,包括寄存器的值、调用栈信息、全局变量和局部变量的值等。开发人员可以使用调试工具(如GDB)加载Core dump文件,分析这些信息以找出程序崩溃的原因。

可以通过ulimit -c 10240将core文件的大小限制修改为10240字节。云服务器上通常默认core文件大小限制为0,出现错误时可能导致core文件迅速填满。我们可以根据需要修改其大小限制。生成的文件名为core.pid,其中pid是出错进程的pid。例如,假设test进程发生错误,其pid为12314,我们可以在GDB模式下输入gdb test core.12314来打印错误信息和原因。

二、信号的保存

  1. 前置概念

实际执行信号处理动作称为信号递达。信号从产生到递达之间的状态称为信号未决。被阻塞的信号会保持在未决状态,直到进程解除对此信号的阻塞,才会执行递达的动作。

【Linux】进程信号的发送和保存

  1. 阻塞信号

信号被阻塞时,会进入信号未决状态。阻塞功能通过一个31位的位图block实现,对应1到31号信号。当对应比特位为1时,表示该信号被阻塞,为0则表示不阻塞。如果信号被阻塞,则进入阻塞态;如果没有被阻塞,则进入未决状态。

  1. 保存信号

未决状态的作用是保存信号,通过位图pending实现。pending与block一致,对应的下标和信号编号一一对应。当对应比特位为1时,表示该信号处于未决状态,为0则表示信号已递达。实际上,block和pending都用于保存信号,但由于有两个位图,我们分开讨论。

  1. 信号递达

信号递达后,会执行相应的行为,包括SIG_DFL(默认处理动作)、SIG_IGN(忽略)和自定义处理sighandler。

【Linux】进程信号的发送和保存

  1. 总结

【Linux】进程信号的发送和保存

一个信号首先经过block,如果block为0,则来到pending,如果pending为0,则来到handler执行动作。9号和19号信号是特例,它们不能被阻塞和保存,一旦发出直接执行handler,对应的行为只能是默认动作终止和暂停。

onewo-rtlinux
onewo-rtlinux

Linux 实时编程助手。生成、审查并修改用于周期性控制任务和中断驱动程序的 C 代码。强制实施实时调度策略。

下载

三、信号集操作函数

信号集操作函数用于操作信号集,sigset_t是操作系统提供的数据类型,用于描述位图。以下是信号集操作函数:

#include <signal.h>
int sigemptyset(sigset_t *set); // 将位图全部设置为0
int sigfillset(sigset_t *set); // 将位图全部设置为1
int sigaddset(sigset_t *set, int signo); // 将位图中的某一位设置为1
int sigdelset(sigset_t *set, int signo); // 将位图中的某一位设置为0
int sigismember(const sigset_t *set, int signo); // 判断一个信号是否在信号集中,不在返回0,在返回1,出错返回-1
</signal.h>
  1. 设置block位图

sigprocmask是一个重要的系统调用,用于检查和修改进程的信号掩码(阻塞信号集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
</signal.h>

返回值:成功返回0,失败返回-1。

how参数指定对信号掩码的操作方式:

how取值 含义 示例说明
SIG_BLOCK 将set所指向的信号集中的信号添加到当前的信号掩码中,即阻塞set中的信号 若当前信号掩码已阻塞SIGINT,使用SIG_BLOCK并传入包含SIGTERM的信号集,SIGTERM也会被阻塞
SIG_UNBLOCK 从当前的信号掩码中移除set所指向的信号集中的信号,即解除对set中信号的阻塞 若当前信号掩码阻塞了SIGINT和SIGTERM,使用SIG_UNBLOCK并传入包含SIGINT的信号集,SIGINT信号的阻塞状态将被解除
SIG_SETMASK 将当前的信号掩码设置为set所指向的信号集,覆盖原来的信号掩码 若原信号掩码阻塞SIGINT,使用SIG_SETMASK并传入包含SIGTERM的信号集,信号掩码将只阻塞SIGTERM

set参数指向一个sigset_t类型的信号集,包含要操作的信号。如果how的值为SIG_BLOCK或SIG_UNBLOCK,set表示要添加或移除的信号集;如果how的值为SIG_SETMASK,set表示要设置的新信号掩码。如果该参数为NULL,则不改变当前的信号掩码,仅获取当前信号掩码,此时oset不能为NULL。

oset参数指向一个sigset_t类型的信号集,用于存储调用sigprocmask之前的信号掩码。如果不需要保存旧的信号掩码,可以将该参数设置为NULL。

  1. 设置pending位图

sigpending用于获取进程当前未决信号集。

#include <signal.h>
int sigpending(sigset_t *set);
</signal.h>

返回值:成功返回0,失败返回-1。

set参数用于存储当前进程中处于未决状态(即已发送但由于被阻塞而尚未被处理)的信号集。

  1. 设置handler行为

信号处理行为有三种情况:默认、忽略和自定义。自定义处理可以通过signal函数实现,此前已有介绍,不再赘述。

四、验证信号保存行为

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

// 打印出位图
void PrintPending(const sigset_t &pset) {
    for(int i = 31; i >= 1; i--) {
        cout << (sigismember(&pset, i) ? 1 : 0);
    }
    cout << endl;
}

// 信号处理函数
void handler(int sig) {
    cout << "Caught signal " << sig << endl;
}

int main() {
    sigset_t newmask, oldmask, pendmask;

    // 初始化信号集
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGINT);

    // 阻塞SIGINT信号
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);

    // 打印当前未决信号集
    while(1) {
        sigpending(&pendmask);
        PrintPending(pendmask);
        sleep(1);
    }

    // 解除SIGINT信号的阻塞
    sigprocmask(SIG_SETMASK, &oldmask, NULL);

    return 0;
}
</unistd.h></signal.h></iostream>

在3秒后按下ctrl+c,捕捉信号函数不会工作,说明信号被阻塞了。15秒后自动解除阻塞,立即打印出handler函数定义要打印的信息,再按ctrl+c就正常执行handler行为。

【Linux】进程信号的发送和保存

热门AI工具

更多
切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2411

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

494

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

422

2026.02.12

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

509

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1658

2024.03.01

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

3725

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

1530

2025.09.18

c++ 全局变量
c++ 全局变量

本专题整合了c++全局变量的使用、定义、作用域等等内容,阅读专题下面的文章了解更多详细内容。

199

2026.03.17

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

60

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Conan 2 新特性与架构变化
Conan 2 新特性与架构变化

共0课时 | 0人学习

Conan 2 安装指南
Conan 2 安装指南

共0课时 | 0人学习

《Debugging with GDB》用户手册
《Debugging with GDB》用户手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn