Linux系统编程系列之进程间通信(IPC)-信号

news2024/11/26 23:19:31

一、什么是信号

        信号是进程间通信的一种方式,它是异步通信的。而异步的意思就是不同步,事件的发生和处理没有协同。

二、信号的特性

             Linux/Unix系统下,信号总共分成两大类,一类是最常用的标准信号,另一类是后面的引入的实时信号。一共有62个信号,前31个是标准信号,后面31个是实时信号。注意没有32,33号。

        1、标准信号

        (1)不排队,信号的响应会相互嵌套。

        (2)如果目标进程没有及时响应,那么随后到达的相同信号将会被丢弃。

        (3)每个信号都对应一个系统事件(除了SIGUSR1和SIGUSR2),当这个事件发生时,将产生这个信号。

        (4)在进程的挂起信号中,进程会优先响应实时信号。

        2、实时信号

        (1)实时信号的响应次序按接收顺序排队。如果收到相同的信号的则不会嵌套,但是如果是不同的信号则会导致嵌套。

        (2)即使相同的实时信号被同时发送多次,也不会被丢弃,而会依次按个响应。

        (3)实时信号没有特殊的系统事件与之对应。

        (4)实时信号在挂起队列中信号值越大,优先级越高。

三、信号的生命周期

        所谓信号的生命周期,指的是信号从产生到被响应完毕的整个过程,这个过程可被描述为:

        1、信号的产生

        信号既可以由特定的事件产生(比如发生了内存访问异常导致产生信号SIGSEGV),也可以由用户主动发起(比如调用了kill()函数),不管是哪种方式产生的信号,其本质都是触发了内核的信号发生器,并向特定进程(即目标进程)传递的过程。

// kill()函数接口介绍
#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);

参数:
    pid: 要接收信号的进程号
    sig: 信号的编号
返回值:成功返回0, 失败返回-1.

        2、信号的挂起

        每个进程都保留有一个挂起信号集,所有被发送到这个进程的信号首先被放入到这个信号集(进程处于非执行状态),挂起信号集存储了进程的待处理信号,这些信号必须要等到进程被系统调度(占用CPU执行的时候),真正执行的时候才能被进一步响应。

        3、信号的响应(处理)

        信号的响应总共有如下四种方式:

        (1)屏蔽(阻塞):延缓对信号的响应,直到解除对该信号的屏蔽为止。

        (2)捕捉:执行一个预先设置的与信号相关联的响应函数。

        (3)默认:按信号默认的情况处理。

        (4)忽略:直接丢弃该信号。

注意:系统中9号,19号信号是不允许被挂起或捕获的,只允许对他们进行默认处理

四、信号的响应(处理)        

       1、信号的捕捉

        给函数指定关联函数的接口是:        

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

// 翻译过来就是
void (*signal(int sig, void (*func)(int)))(int);

// 函数名为:signal
// 参数为:
    int sig, 信号的编号
    void (*func)(int), 关联的函数,函数的参数是int, 返回值是void
// 返回值:void (*)(int);

        2、信号的默认处理

        如果程序没有对信号做任何预先准备,那么当信号到达时,则会按照信号的默认规则进行响应,具体默认规则可使用如下命令查阅:

man 7 signal

     列表中的Action 一列就是系统对信号的默认处理规则,默认规则如下:

        (1)Term:中断目标进程

        (2)Core:中断目标进程,且产生核心转储文件core

        (3)Stop:暂停目标进程,直到收到信号SIGCONT

        (4)Cont:恢复目标进程运行

        (5)Ign:忽略信号

          3、信号的忽略

信号的忽略就是直接将收到的信号丢弃

signal(SIGINT, SIG_IGN);

          4、信号的屏蔽

屏蔽信号实际上就是暂缓对信号的响应,采用如下函数进行对信号的屏蔽

#include <signal.h>

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

// 参数解析:
1、how:操作命令字,比如阻塞、解除阻塞等
    SIG_BLOCK:阻塞set中的信号(原有正在阻塞的信号保持阻塞)
    SIG_SETMASK:阻塞set中的信号(原有正在阻塞的信号自动解除)
    SIG_UNBLOCK:解除set中的信号

2、set:当前要操作的信号集
3、oldset:若为非空,则将原有阻塞信号集保留到该oldset中
注意:该函数的操作参数不是单个信号,而是信号集,
这意味着我们可以同时对多个信号设置阻塞或者解除阻塞


// 信号集操作函数组
int sigemptypset(sigset_t *set);    // 清空信号集set
int sigfillset(sigset_t *set);    // 将所有信号加入信号集set中
int sigaddset(sigset_t *set, int signum); // 将信号signum添加到信号集set中
int sigdelset(sigset_t *set, int signum); // 将信号signum从信号集set中剔除
int sigsimember(const sigset_t *set, int signum); // 测试信号signum是否在信号集set中

五、案例

        1、信号的捕捉

// 信号的捕捉操作示例

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void func(int sig)
{
    printf("call func\n");
    printf("catch signal:%d\n", sig);
}

int main(int argc, char *argv[])
{
    // 设置信号响应函数,捕捉34号信号,当捕获到34号信号时,执行func函数
    // 注意设置后,不会执行func函数,signal()应该尽量写在前面
    signal(34, func);   

    printf("my pid is %d\n", getpid()); // 打印本进程ID号,方便从命令行发送信号
    printf("set signal 34...\n");

    while(1)
    {
        sleep(1);
    }
    
    return 0;
}

 

// 信号的捕捉操作示例

#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void func(int sig)
{
    printf("call func\n");
    printf("catch signal:%d\n", sig);
}

int main(int argc, char *argv[])
{
    printf("my pid is %d\n", getpid()); // 打印本进程ID号,方便从命令行发送信号
    printf("set signal 34...\n");

    while(1)
    {
        sleep(1);
    }

    // 如果放在这里注册信号响应函数,也能捕捉到信号,但是会有意想不到的结果
    signal(34, func);  
    
    return 0;
}

        2、信号的屏蔽

// 信号的阻塞(屏蔽)操作示例

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>

void func(int sig)
{
    printf("call func\n");
    printf("catch signal %d\n", sig);
}

int main(int argc, char *argv[])
{
    // 注册信号响应函数
    signal(34, func);
    printf("my pid is %d\n", getpid());

    // 设置信号阻塞,阻塞34号信号
    sigset_t set;
    sigemptyset(&set);  // 清空信号集
    sigaddset(&set, 34);    // 把34信号添加到信号集中
    
    if(sigprocmask(SIG_SETMASK, &set, NULL) == -1)  // 把信号集中的所有信号设置为阻塞
    {
        perror("设置阻塞失败\n");
    }

    sleep(10);   // 10秒内不会对34号进行处理

    if(sigprocmask(SIG_UNBLOCK, &set, NULL))   // 解除信号集中的阻塞信号
    {
        perror("设置阻塞失败\n");
    }

    while(1)
    {
        sleep(1);
    }



    return 0;
}

六、总结

        信号是进程间异步通信的方式,Linux系统下有62个信号,1~31号是标准信号,34~64是实时信号,对信号的响应方式有四种,分别是屏蔽(阻塞),捕捉,默认处理和忽略。注册信号响应函数的语句应该放在主函数体内前面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/940761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python怎么解决性能问题?

Python的性能问题可以通过以下一些方法来解决或改善&#xff1a; 使用更高效的算法和数据结构&#xff1a; 选择适当的数据结构和算法可以显著提升代码的性能。了解不同算法的时间复杂度和空间复杂度&#xff0c;选择最适合问题的解决方案。 优化代码逻辑&#xff1a; 仔细审查…

yolov8使用C++推理的流程及注意事项

1.下载yolov8项目源码GitHub - ultralytics/ultralytics: NEW - YOLOv8 &#x1f680; in PyTorch > ONNX > OpenVINO > CoreML > TFLite 2.下载opencvReleases - OpenCV,建议版本>4.7.0,选择下载源码&#xff0c; windows版本由于使用的编译器与我们所使用的m…

5年测试,面试结束后被HR发朋友圈怼了..(心塞)

前一阵子向朋友诉苦&#xff0c;我在参加字节跳动面试的时候被面试官怼得哑口无言&#xff0c;场面让我一度十分尴尬。 印象最深的就是下面几个问题&#xff1a; 根据你以前的工作经验和学习到的测试技术&#xff0c;说说你对质量保证的理解&#xff1f; 非关系型数据库和关系型…

关于MySQL数据页的一些认识

1. 一个数据页有很多个槽&#xff0c;每个槽对应一个分组&#xff0c;槽指向分组的最大数据行记录&#xff0c;查找时通过二分法定位数据所在组 从数据页的角度看 B 树 | 小林coding 【Mysql】InnoDB 引擎中的页目录 - 知乎 2. 每个行记录是通过单链表来存储的 3. 数据页之…

教会你怎么使用SpringMVC 文件上传

&#x1f600;前言 教会你怎么使用SpringMVC 文件上传 &#x1f3e0;个人主页&#xff1a;尘觉主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是尘觉&#xff0c;希望我的文章可以帮助到大家&#xff0c;您的满意是我的动力&#x1f609;&#x1f609; 在csdn获…

java入坑之网络编程

一、 网络基础知识 1.1网卡 1.2IP地址 1.3端口 1.4保留IP 1.5网络协议 二、UDP 编程 2.1相关概念 计算机通讯&#xff1a;数据从一个IP的port出发&#xff08;发送方&#xff09;&#xff0c;运输到另外一个IP的port&#xff08;接收方&#xff09; UDP&#xff1a;无连接无…

EXSI技术--Exsi简介与安装

1.EXSI简介 了解可直接安装到您的物理服务器的、可靠的裸机 Hypervisor。通过直接访问并控制底层资源,VMware ESXi可有效地对硬件进行分区,以便整合应用并降低成本。它是业界领先的高效体系架构,在可靠性、性能和支持方面树立了行业标杆。(裸金属架构) VMware vSphere的虚拟…

CSDN每日一练 |『影分身』『小鱼的航程(改进版)』『排查网络故障』2023-08-25

CSDN每日一练 |『影分身』『小鱼的航程&#xff08;改进版&#xff09;』『排查网络故障』2023-08-25 一、题目名称&#xff1a;影分身二、题目名称&#xff1a;小鱼的航程(改进版)三、题目名称&#xff1a;排查网络故障 一、题目名称&#xff1a;影分身 时间限制&#xff1a;1…

【java并发编程的艺术读书笔记】ConcurrentHashMap是如何保证线程安全的

ConcurrentHashMap HashMap的线程安全问题 并发环境下HashMap可能会导致程序死循环&#xff0c;原因是put操作可能会使得HashMap中的链表结构成环&#xff0c;导致无法找到next节点&#xff0c;无限循环 HashTable为什么效率低 HashMap是使用synchronized来保证县城安全的&…

计算机网络MTU和MSS的区别

在计算机网络中&#xff0c;MTU代表最大传输单元&#xff08;Maximum Transmission Unit&#xff09;&#xff0c;而MSS代表最大分节大小&#xff08;Maximum Segment Size&#xff09;。 1.MTU&#xff08;最大传输单元&#xff09;&#xff1a; MTU是指在网络通信中&#x…

C语言初阶测评题:测试你的基础知识和编程技能!!

&#x1f493;博客主页&#xff1a;江池俊的博客⏩收录专栏&#xff1a;C语言刷题专栏&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐ 文…

【C语言】探讨蕴藏在表达式求解中的因素

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;C语言 &#x1f525;该篇将探讨 操作符 和 类型转换 对表达式求解的影响。 目录&#xff1a; 隐式类型转换算术转换操作符的属性❤️ 结语 隐…

调用自实现MyGetProcAddress获得CreateFileA函数并调用创建写入文件

写文件如下 #include <iostream> #include <Windows.h>typedef HANDLE(WINAPI* CreateFileAFunc)(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);DWORD MyGetProcAddress(_In_ HMODULE hModule,_In_ LPCSTR lpProcName ){PIMAGE_DOS_HEADE…

南京邮电大学《基于编译原理的表达式计算器》

文章目录 一、课题内容和要求二、课题需求分析1 过程分析2 设计分析 三、课题相关数据结构及算法设计1 主要数据结构2 主要算法流程3 词法分析4 语法分析5 中间代码生成6 LR语法分析程序6.1识别活前缀的DFA6.2 SLR(1)分析表6.3 分析过程 四、源程序代码1 源代码层次结构2.1 ana…

第十套教程序言:阻止对Sub和Functions的直接访问

【分享成果&#xff0c;随喜正能量】引擎利用后退的力量&#xff0c;引发更大的动能&#xff1b;空气经过压缩&#xff0c;更具爆破的威力。所谓"退一步想&#xff0c;海阔天空。"正可点破我们迷妄执着的盲点。。 《VBA高级应用30例》&#xff08;10178985&#xff0…

前端Excel导入数据后端数据库表未添加主键导致Excel导入数据重复

Java对Excel等文档解析上传到数据库或服务器问题记录 临时功能展示数据库表未添加主键导致Excel导入数据重复 如图,问题发现是因为Excel表中只有两千多条数据但导入数据库后却有五千多条,当时在代码中疯狂找原因也未果,最后尝试给数据库添加主键解决问题! 去除重复数据 总条…

渗透测试漏洞原理之---【CSRF跨站请求伪造】

文章目录 1、CSRF概述1.1、基本原理1.1.1、基本概念1.1.2、关键点1.1.3、目标 1.2、CSRF场景1.2.1、银行支付转账1.2.2构造虚假网站1.2.3、场景建模 1.3、CSRF类别1.3.1、POST方式 1.4、CSRF验证1.4.1、CSRF PoC Generator 2、CSRF攻防2.1、CSRF实战2.1.1、与XSS 漏洞相结合 2.…

构建简单的Node.js HTTP服务器,发布公网远程访问的快速方法

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

超实用的快递单号一键查询方法,帮你省时又省力

快递查询是我们日常生活中经常需要进行的操作&#xff0c;然而&#xff0c;当我们有多个快递单号需要查询时&#xff0c;逐个查询就显得非常繁琐和耗时。为了解决这个问题&#xff0c;今天给大家推荐一款实用的软件——【固乔快递查询助手】。 首先&#xff0c;在浏览器中搜索并…

单片机最小系统构成

51单片机最小系统构成 &#xff1a; 四部分组成 &#xff08;1&#xff09;晶振电路 &#xff08;2&#xff09;复位电路 &#xff08;3&#xff09;电源电路 &#xff08;4&#xff09;下载电路 &#xff08;1&#xff09;晶振电路干嘛的&#xff1f; 单片机需要 时钟 来…