【Linux】进程间通信之信号机制2

news2024/9/26 3:27:59

文章目录

  • 信号阻塞代码验证
    • 验证信号的阻塞
    • 验证信号的阻塞不影响信号注册
    • 验证可靠信号不会丢信号,不可靠信号会丢信号
    • 验证9号和19号信号不能被阻塞
  • 用信号解决僵尸进程
  • volatile关键字

信号阻塞代码验证

在上篇详解信号机制的博文中,我们提到了设置阻塞位图的函数sigprocmask函数:

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

现在我们用代码来演示一下:

首先了解一下位图的设置函数:

在这里插入图片描述

验证信号的阻塞

代码如下:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <signal.h>
  4 void handler(int signum)
  5 {
  6   printf("signum : %d\n",signum);
  7 }
  8 int main(){
  9   signal(2, handler);
 10   sigset_t set;
 11   sigaddset(&set, 2);                                       
 12   sigprocmask(SIG_BLOCK, &set, NULL);
 13   while(1){
 14     printf("Hello!\n");
 15     sleep(1);
 16   }
 17   return 0;
 18 }

执行结果:
在这里插入图片描述

验证信号的阻塞不影响信号注册

验证可靠信号不会丢信号,不可靠信号会丢信号

验证思路:

我们选取两个信号2(非可靠信号)、40(可靠信号),首先把这两个信号阻塞,其次再接触这两个信号的阻塞,观察2号信号和40号信号处理几次,同时也证明可靠信号不能丢失信号,非可靠信号会丢失信号

代码如下:

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <signal.h>
  4 void sigcallback(int sig){                                                                                                                               
  5     printf("sigcallback recv sig: %d\n", sig);
  6 }                                             
  7  
  8 int main(){
  9   signal(2, sigcallback);
 10   signal(40, sigcallback);
 11                           
 12   sigset_t set;
 13   sigemptyset(&set);
 14   sigaddset(&set, 2);
 15   sigaddset(&set, 40);
 16                       
 17   sigprocmask(SIG_BLOCK, &set, NULL);
 18   getchar();                         
 19   sigset_t oldset;
 20   sigemptyset(&oldset);
 21   sigprocmask(SIG_SETMASK, &oldset, NULL);
 22                                           
 23   while(1){       
 24     printf("i am main, sleep(1)\n");
 25     sleep(1);                             
 26   }          
 27   return 0;
 28 }        

首先代码是阻塞的,我们发送多次信号,但是都是反应,接着我们随便敲了一个字符,此时启动getchar后面的代码,也就是解除阻塞,此时可以看到程序对之前阻塞了的信号的处理情况

执行结果:

在这里插入图片描述

验证9号和19号信号不能被阻塞

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <signal.h>
  4 void handler(int signum)
  5 {
  6   printf("signum : %d\n",signum);    
  7 }
  8 
  9 int main(){
 10   signal(9, handler);
 11   signal(19, handler);
 12 
 13   sigset_t set;
 14   sigfillset(&set); // 位图全部置为1
 15 
 16   sigprocmask(SIG_SETMASK,&set,NULL);
 17   while(1)
 18   {
 19     printf("Hello!\n");
 20     sleep(1);
 21   }
 22 
 23   return 0;                                             
 24 }

执行结果:

9号信号和19号信号不执行我自定义的处理方式,依旧按照原有方式处理信号

用信号解决僵尸进程

我们之前在如何解决僵尸问题的时候,提到了用wait或者waitpid函数,但是这两个函数都有不方便的地方,wait函数在调用时,父进程一直处于阻塞等待等待子进程退出状态,waitpid函数需要配合循环,这样的结果就是我们的父进程得不到充分利用,只等着回收子进程退出状态信息了,这里我们可以用信号,对子进程进行回收。

代码如下:

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

void sigcallback(int sig){
    printf("sigcallback recv sig: %d\n", sig);
    wait(NULL);
}

int main(){
    /*
     * 目的: 解放父进程, 让父进程创建子进程之后, 还能执行父进程的代码逻辑。 并且,还能防止子进程变成僵尸进程
     *
     * 做法:
     *    将SIGCHLD信号的处理方式进行自定义
     *    在自定义的函数当中调用wait/waitpid函数
     *
     *    子进程退出之后, 会向父进程发送SIGCHLD信号
     *    父进程回调自定义处理函数, 从调用wait/waitpid函数, 回收子进程的退出状态信息
     * */

    /* 1. 自定义处理SIGCHLD信号 */
    signal(SIGCHLD, sigcallback);

    /*
     * 2. 创建子进程了
     * */

    pid_t ret = fork();
    perror("fork");
    if(ret < 0){
        perror("fork");
        return 0;
    }else if(ret == 0){
        //child
        sleep(5);
        printf("i am child\n");
    }else{ //ret > 0
        //father
        while(1){
            printf("i am father, exec father process code\n");
            sleep(1);
        }
    }
    return 0;
}

执行结果:

在这里插入图片描述

volatile关键字

volatile关键字作用:保证内存可见性,告诉编译器,该变量的值可能会在程序的控制之外被修改,因此编译器不应该对该变量的读写进行优化或缓存。每次CPU要计算的数据都是从内存中获取,拒绝编译时优化的方案(从寄存器当中获取),gcc/g++的编译选项“-O0, O1, -O2,-O3“,优化级别越来越高。(理解优化级别越高,程序可能执行的越快)优化级别越高就从寄存器中取值的可能性越大。

代码演示:

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

int g_val = 1;

void sigcallback(int sig){
    printf("sigcallback recv sig: %d\n", sig);
    g_val = 0;
}

int main(){
    signal(2, sigcallback);
    while(g_val){
    }

    printf("hhh, jump down\n");
    return 0;
}

运行结果:

在这里插入图片描述

上述代码运行按下ctrl+c向进程发送2号信号,进程直接结束了,说明g_val的值被修改了,这是因为我们在编译时没有对程序进行优化,这时候是从内存中拿的

我们试着优化一下,执行结果:

在这里插入图片描述

当我们试着将g_val用volatile关键字声明:

volatile int g_val = 1;

再执行:

在这里插入图片描述
此时优化就不管用了,保证了从内存中读取数据

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

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

相关文章

RISC-V公测平台发布 · 数据库在RISC-V服务器上的适配评估

前言 上一期讲到YCSB在RISC-V服务器上对MySQL进行性能测试&#xff08;RISC-V公测平台发布 使用YCSB测试SG2042上的MySQL性能&#xff09;&#xff0c;在这一期文章中&#xff0c;我们继续深入讨论RISC-V数据库的应用。本期就继续利用HS-2平台来测试数据库软件在RISC-V服务器…

基于PaddlePaddle实现的声纹识别系统

前言 本项目使用了EcapaTdnn、ResNetSE、ERes2Net、CAM等多种先进的声纹识别模型&#xff0c;不排除以后会支持更多模型&#xff0c;同时本项目也支持了MelSpectrogram、Spectrogram、MFCC、Fbank等多种数据预处理方法&#xff0c;使用了ArcFace Loss&#xff0c;ArcFace loss…

❤echarts折线图完整使用及详细配置参数

❤echarts折线图完整使用及详细配置参数 进入echarts官网 查看案例&#xff0c;下面说说一些echarts图的调节 一、配置echarts具体参数 01 基础版本的折线图 option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data…

Charles通过逍遥模拟器抓包APP,亲测可用

1.设置http代理. Proxy-->Proxy settings 2.设置ssl proxy-->ssl proxying settings 3.Charles安装证书 弹出证书安装界面,点击"安装证书" 选择当前用户, 选择: 将所有的证书都放入下列存储: 直接下一步,最后确定提示"导入成功" 4.接着设置Charles安…

年薪47500美元|眼科硕士赴弗吉尼亚大学从事博士后研究

K医生只有医学硕士学位&#xff0c;起初只考虑申请访问学者&#xff0c;最终我们为其争取到“Post-Doctoral Research Associate”&#xff08;博士后研究助理&#xff09;职位&#xff0c;年薪47500美元&#xff0c;大大超出了本人的预期。 K医生背景&#xff1a; 申请类型&a…

提升管班小诀窍

在传统教育中&#xff0c;将考试结果告知家长一直是一项相对麻烦的任务。老师们不得不一个一个的打电话或发短信&#xff0c;耗费大量时间和精力。然而&#xff0c;现在有了易查分&#xff0c;老师们可以轻松地创建自己的成绩查询系统&#xff0c;大大简化了这项任务。 好消息&…

iOS代码混淆

文章目录 一、混淆的原理二、实现混淆1. 创建文件2. 将文件拖导入目录中3. 将以下脚本拷贝到刚新建的confuse.sh文件中4. 修改文件权限5. 修改项目配置6. 添加需要混淆的方法名7. 配置PCH文件8. 运行效果 一、混淆的原理 这里使用的混淆的原理是&#xff0c;用一串随机生成的字…

百华劳保|听厂家聊聊如何检测防水劳保鞋?

说起防水劳保鞋大家可能并不陌生&#xff0c;在有积水或水利工程这些工作场景中使用&#xff0c;是防止水渗透鞋子的安全防护鞋。许多企业会为员工发放防水劳保鞋&#xff0c;在采购时一般都需要进行防水测试&#xff0c;提供相对应的检测报告。今天百华小编与大家聊聊都是如何…

毛利率下滑至负数,但小鹏汽车仍有信心

KlipC报道&#xff1a;8月18日周五&#xff0c;港股盘后美股盘前&#xff0c;小鹏汽车公布截至2023年6月30日的二季度业绩&#xff0c;据数据显示本季度小鹏营收50.6亿人民币&#xff0c;略超预期。但受G3i的存货减值及存货购买合约损失拖累&#xff0c;毛利率下滑至-3.9&#…

vellum (Discovering Houdini VellumⅡ柔体系统)学习笔记

视频地址&#xff1a; https://www.bilibili.com/video/BV1ve411u7nE?p3&spm_id_frompageDriver&vd_source044ee2998086c02fedb124921a28c963&#xff08;搬运&#xff09; 个人笔记如有错误欢迎指正&#xff1b;希望可以节省你的学习时间 ~享受艺术 干杯&#x1f37b…

一“码”当先,PR大征集!2023 和RT-Thread一起赋能开源!

活动地址&#xff1a;https://club.rt-thread.org/ask/article/3c7cf7345ca47a18.html 活动介绍 「一“码”当先&#xff0c;PR大征集&#xff01;」是一项为了鼓励开发者积极参与开源软件开发维护的活动。 你可在Github RT-Thread&#xff08; https://github.com/RT-Thread …

学习ts(五)类

定义 是面向对象程序设计&#xff08;OOP&#xff09;实现信息封装的基础 类是一种用户定义的引用数据类型&#xff0c;也称类类型 JavaScript的class,虽然本质是构造函数&#xff0c;但是使用起来已经方便了许多&#xff0c;js中没有加入修饰符和抽象类等特性 ts的class支持面…

飞机打方块(五)游戏音乐

一、新建节点 1.在Start场景中新建Music节点&#xff0c;绑定canvas 2.在Game场景中新建Music节点 3.新建节点 4.新建Music脚本&#xff0c;绑定Canvas Music.ts const { ccclass, property } cc._decorator;ccclass export default class NewClass extends cc.Component {p…

【静态时序分析STA(邸志雄)/2023年8月20日】

内容&#xff1a;TCL语言&#xff08;PT&#xff09;&#xff0c;静态时序分析基础&#xff08;工艺库、STA环境、时序检查方法、多时钟等特殊时序分析&#xff09;&#xff0c;SDC&#xff08;tcl设计约束&#xff09; CTS&#xff1a;clock tree systhesis Tsu建立时间/Th保…

实验四 SD 卡启动盘制作

【实验目的】 掌握 SD 卡启动盘的制作方法 【实验环境】 FS4412 实验平台 【实验步骤】 烧写工具默认从 0 扇区开始烧写&#xff0c;这里我们自己在 uboot 之前放一个512 字节的空镜像 将资料中“u-boot 镜像”中的 u-boot-fs4412.bin 拷贝到 ubuntu 的家目录下 在终端输…

升级家庭网络!Wi-Fi 7让你流畅体验网速飞快的3大原因

与我们的智能手机和笔记本电脑不同,即使是最好的Wi-Fi路由器也是我们家中最有可能被视为理所当然的技术——也就是说,直到出现问题。然而,一旦Wi-Fi 7成为主流,这种情况可能很快就会改变。 虽然从Wi-Fi 6到Wi-Fi 6E的飞跃引入了更快的6 GHz频段,但这还不足以让大多数人升…

善于打仗的人,没有特别大的名气和勇功

善于打仗的人&#xff0c;没有特别大的勇功 【安志强趣讲《孙子兵法》第15讲】 【原文】 见胜不过众人之所知&#xff0c;非善之善者也&#xff1b;战胜而天下曰善&#xff0c;非善之善者也。 【趣讲白话】 预判胜负没有超出常人的见识&#xff0c;算不上高明中最高明的&#x…

抓住WhatsApp 营销风口,做全球电商领跑者

您的电子邮件营销活动效果是否一直不理想&#xff1f;不妨考虑 WhatsApp营销&#xff0c;一种实时通讯营销&#xff0c;可帮助企业接触更广泛的受众&#xff0c;与客户建立个人联系并最终增加销售额。还可以再借助具有强大功能的全渠道客户服务工具&#xff0c;例如SaleSmartly…

初出茅庐的小李博客之STM32CubeMx配置USART1增加打印功能

1.创建基于STM32F03C8T6工程 1.1配置时钟 选择外部高速时钟源HSE 1.2配置系统时钟树使其达到最大时钟72MHz&#xff08;最大系统时钟&#xff09; 配置串口1 生成代码 具体工程配置可参考上几篇博客&#xff0c;地址 初出茅庐的小李博客之STM32CubeMx驱动WS2812B实现幻彩&a…