信号捕捉、可重入函数、volatile、SIGCHLD

news2024/12/21 4:36:30

个人主页:Lei宝啊 

愿所有美好如期而遇


信号捕捉

signal

这个函数我们前面关于信号的文章多次提及,这里重点介绍sigaction。

sigaction

只需要看红色框住的属性即可,其余属性我们不使用,不用多管。第一个handler和signal的第二个参数意义是一样的,sa_mask是设置阻塞信号,sa_flags直接设为0即可。

在这里我们要提到的是:当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止,避免了嵌套式的信号处理。

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

using namespace std;

void Print()
{
    sigset_t pending;
    sigpending(&pending);

    for (int i = 31; i > 0; i--)
    {
        if (sigismember(&pending, i))
            cout << "1";
        else
            cout << "0";
    }
    cout << endl;
}

void handler(int signo)
{
    cout << "signo" << endl;

    int cnt = 10;
    while(cnt)
    {
        sleep(1);
        cnt--;
        Print();
    }

}

int main()
{

    struct sigaction sig;

    //这里其实不需要创建block,可以用sig系列函数直接操作sa_mask
    sigset_t block;
    sigemptyset(&block);

    sig.sa_flags = 0;
    sig.sa_mask = block;
    sig.sa_handler = handler;

    int val = sigaction(2, &sig, nullptr);
    if(val < 0) cout << "error" << endl;
    //signal(2, handler);

    while(true)
    {
        Print();
        sleep(1);
    }

    return 0;
}

我们也证明了这一点。

可重入函数

在我们执行insert函数时,进程时间片结束,检测到信号,并进行了捕捉,在捕捉函数中又调用了insert函数,最终导致未定义结果,像上例这样,insert函数被不同的控制流程调用,有可能在第一次调用还没返回时就再次进入该函数,这称为重入。

如果一个函数符合以下条件之一则是不可重入的:

  • 调用了malloc或free,因为malloc也是用全局链表来管理堆的。
  • 调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构

volatile

volatile 作用:保持内存的可见性,告知编译器,被该关键字修饰的变量,不允许被优化,对该变量的任何操作,都必须在真实的内存中进行操作。

下面我们写个代码举例:

#include <iostream>
#include <signal.h>

using namespace std;

int flag = 0;

void handler(int signo)
{
    flag = 1;
    cout << "flag = " << flag << endl;  
}

int main()
{

    signal(2, handler);
    while(!flag);

    cout << "process exit " << endl;
    return 0;
}

我们首先关闭优化进行编译运行:

接着我们打开优化:

这是因为编译器开启优化后,在主函数中没有检测到flag将会被做任何修改,于是将他放在了寄存器中,将来取flag值就去寄存器拿,而我们在内存中堆flag的修改不会对结果有任何影响了。

接下来我们给flag变量加上volatile修饰:

volatile int flag = 0;

SIGCHLD

子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <wait.h>
using namespace std;

void handler(int signo)
{
    while(true)
    {
        //阻塞等待
        int val = waitpid(-1,nullptr,WNOHANG);
        if(val <= 0) break;
        else cout << "wait success" << endl;
    }
}

int main()
{

    signal(SIGCHLD, handler);

    for(int i=0; i<100; i++)
    {
        int id = fork();
        if(id == 0)
        {
            cout << "I am forked , pid: " << getpid() << endl;
            sleep(1);
            exit(0);
        }
    }

    while(1) sleep(1);

    return 0;
}

我们解释一下handler函数,首先,由于可能会有多个子进程结束,所以我们需要循环等待,再一个,因为可能不是所有子进程都释放了,所以我们选择非阻塞等待,将已经结束的子进程回收后跳出死循环,等待其他子进程结束发送信号调用自定义处理方法。

另一种处理方式:

事实上,由于UNIX 的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调 用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。系统默认的忽略动作和用户用sigaction函数自定义的忽略 通常是没有区别的,但这是一个特例。此方法对于Linux可用,但不保证在其它UNIX系统上都可用。

int main()
{

    signal(SIGCHLD,SIG_IGN);

    for(int i=0; i<100; i++)
    {
        int id = fork();
        if(id == 0)
        {
            cout << "I am forked , pid: " << getpid() << endl;
            sleep(1);
            exit(0);
        }
    }

    while(1) sleep(1);

    return 0;
}

while true ; do ps axj | grep '[s]ig' ; sleep 1; done 

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

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

相关文章

Vim学习笔记01~04

第01章&#xff1a; 遁入空门&#xff0c;模式当道 1.什么是vim Vim是一个高效的文本编辑工具&#xff0c;并且可以在编程开发过程中发挥越来越重要的作用。 事实上&#xff0c;有不少编程高手使用他们来进行代码的开发&#xff0c;并且对此赞不绝口。 2.本系列目的 但是让…

图论基础知识 深度优先(Depth First Search, 简称DFS),广度优先(Breathe First Search, 简称DFS)

图论基础知识 学习记录自代码随想录 dfs 与 bfs 区别 dfs是沿着一个方向去搜&#xff0c;不到黄河不回头&#xff0c;直到搜不下去了&#xff0c;再换方向&#xff08;换方向的过程就涉及到了回溯&#xff09;。 bfs是先把本节点所连接的所有节点遍历一遍&#xff0c;走到下…

Find My头盔|苹果Find My技术与头盔结合,智能防丢,全球定位

头盔是保护头部的装具&#xff0c;是人们交通中不可或缺的工具。头盔具有保护头部、吸收冲击力、减少伤害风险、提高安全性、防止颅脑损伤等功效作用。头盔能够提供额外的保护&#xff0c;减少头部受伤的风险。在日常出行或进行高风险活动过程中&#xff0c;如骑自行车、骑行电…

http忽略ssl认证

我们在发请求时&#xff0c;会遇到需要ssl证书验证的报错&#xff0c;针对该错误以及所使用的不同的创建连接的方式&#xff0c;进行ssl证书忽略 忽略SSL证书的流程 简介&#xff1a;需要告诉client使用一个不同的TrustManager。TrustManager是一个检查给定的证书是否有效的类…

mybatis的使用技巧9——mysql按年、季度、月、周等不同时间维度查询或分组统计

在实际项目开发过程中&#xff0c;按不同时间维度查询业务数据的操作异常频繁。比较多的操作如支持按时间周期范围做列表数据的筛选&#xff0c;或者是按年月日等维度的图表展示&#xff0c;亦或者是首页的概况&#xff0c;三维大屏的展示等&#xff0c;都离不开不同时间周期查…

Pulsar【部署 02】Pulsar可视化工具Manager安装使用

Pulsar Manager 是一个基于 web 的 GUI 管理和监视工具&#xff0c;可帮助管理员和用户管理和监视租户、命名空间、主题、订阅、代理、集群等&#xff0c;并支持对多个环境进行动态配置。 可视化工具Manager安装使用 1.Docker1.1 拉取镜像并启动1.2 设置用户名密码1.3 登录并添…

kaggle之皮肤癌数据的深度学习测试

kaggle之皮肤癌数据的深度学习测试 近期一直在肝深度学习 很久之前&#xff0c;曾经上手搞过一段时间的深度学习&#xff0c;似乎是做轮胎花纹的识别&#xff0c;当初用的是TensorFlow&#xff0c;CPU版本的&#xff0c;但已经很长时间都没弄过了 现在因为各种原因&#xff…

【提示学习】PromptSync论文问题汇总

文章目录 PromptSync: Bridging Domain Gaps in Vision-Language Models through Class-Aware Prototype Alignment and Discrimination&#xff08;2024CVPR&#xff09;1 Introduction2 Related Work2.1 CLIP2.2 TPT 3 Methodology3.1 提出方法PromptSync3.2 类感知原型生成&…

Cgicc搭建交叉编译环境(移植到arm)

Cgicc GUN Project官网连接&#xff1a;Cgicc- GNU Project - Free Software Foundation 1. 下载源码 Cgicc下载地址&#xff1a; [via http] Index of /gnu/cgicc [via FTP] ftp://ftp.gnu.org/gnu/cgicc/ 目前最新版&#xff1a;3.2.20 2. 源码构建原理 一般&#xff…

POCEXP编写—EXP编写实战(1)

TOC 1. 前言 通过上一篇文章的了解&#xff0c;应该都了解了POC是怎么编写的&#xff0c;而且POC和EXP的区别就是POC只能验证漏洞&#xff0c;简单来说就是通过判断特定的响应值来判断是否存在漏洞&#xff0c;而且EXP就需要将响应的内容给返回回来&#xff0c;但是整体在编写…

vue中的mixin(局部混入、全局混入)

一、mixin是什么 Mixin是面向对象程序设计语言中的类&#xff0c;提供了方法的实现。其他类可以访问mixin类的方法而不必成为其子类&#xff1b;Mixin类通常作为功能模块使用&#xff0c;在需要该功能时“混入”&#xff0c;有利于代码复用又避免了多继承的复杂 Vue中的mixin…

低空经济概念

低空经济是指利用低空空域资源&#xff0c;通过低空交通工具和技术创新发展&#xff0c;促进航空产业、旅游、物流、紧急救援等多领域经济增长和产业融合。随着科技的不断进步和航空产业的快速发展&#xff0c;低空经济正逐渐成为全球经济的重要组成部分。 一、低空经济的主要特…

大数据计算引擎中的Calcite

1.Calcite介绍 Calcite是一个动态数据库管理框架&#xff0c;具备数据库管理系统的功能 Calcite具备SQL解析、校验、优化、生成、连接查询等功能 Calcite能够为不同平台和数据源提供统一的查询引擎 2.Calcite能力 比如&#xff0c;对于HBase而言&#xff0c;没有SQL查询的能力…

✨“光纤通信新篇章:BiDi单纤模块的原理与应用”

&#x1f4a1;目录 ❓什么是BiDi单纤模块&#xff1f; &#x1f527;BiDi光模块的工作原理 &#x1f31f;BiDi光模块的优势 &#x1f335;BiDi光模块类型介绍 &#x1f320;BiDi SFP光模块 &#x1f320;BiDi SFP光模块 &#x1f320;BiDi X2光模块 &#x1f320;BiDi …

科技论文网站:中国科技论文在线

文章目录 1. Intro2. Main3. Cons Evaluation彩蛋&#xff1a;科学素质 这是作者最后一次发这种级别的科普文章 1. Intro 中国科技论文在线是经教育部批准&#xff0c;由教育部科技发展中心主办&#xff0c; 利用现代信息技术手段&#xff0c;打破传统出版物的概念&#xff0c…

NLP step by step -- 了解Transformer

Transformer模型 Transformer相关历史 首先我们先看一下有关Transformer模型的发展历史&#xff0c;下面的图是基于Transformer架构的一些关键模型节点&#xff1a; 图片来源于Hugging Face 图片来源于Hugging Face Transformer 架构 于 2017 年 6 月推出。原本研究的重点是…

GITEE 基于OAuth2的API V5版本

为了构建更好的码云生态环境&#xff0c;我们推出了基于OAuth2的API V5版本。 API V5接口使用方式以及Url都参照GitHub&#xff0c;为了各位开发者更好的兼容已经存在的第三方应用。 API 使用条款 OSCHINA 用户是资源的拥有者&#xff0c;需尊重和保护用户的权益。不能在应用…

信创需求激增,国产服务器操作系统赋能数字化转型

信创&#xff0c;即信息技术应用创新&#xff0c;是指在关键领域和环节推进信息技术的自主创新&#xff0c;构建安全可控的信息技术体系。随着数字化转型的加速&#xff0c;信创需求激增&#xff0c;国产服务器操作系统在其中扮演着至关重要的角色。国产服务器操作系统如何赋能…

TikTok营销攻略:如何精准测试与优化品牌营销策略

在当今数字营销的世界中&#xff0c;社交媒体平台已成为吸引目标受众的重要工具。而TikTok&#xff0c;作为一个快速崛起的视频分享平台&#xff0c;在年轻人中享有巨大的流行度。对于那些希望利用这一平台进行营销的品牌和营销人员来说&#xff0c;了解如何在TikTok上测试营销…

[Rust开发]在Rust中使用geos的空间索引编码实例

geos的空间索引用的是STRTree&#xff0c;这是一种基于STR算法的四叉树索引&#xff0c;有如下特点&#xff1a; 使用Sort-Tile-Recursive (STR) 算法创建的仅查询的R-tree空间索引 STR(Sort-Tile-Recursive,递归网格排序) 基本思想是将所有的矩形以“tile”的方式分配到r/n&a…