首页 > 运维 > linux运维 > 正文

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

看不見的法師
发布: 2025-06-21 13:04:01
原创
431人浏览过

一、信号发送

  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,对应的行为只能是默认动作终止和暂停。

三、信号集操作函数

信号集操作函数用于操作信号集,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】进程信号的发送和保存

以上就是【Linux】进程信号的发送和保存的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号