[Linux学习笔记] 浅谈信号(文章含不少学习资源)

news2025/2/24 0:12:29

百金买骏马,千金买美人,万金买爵禄,何处买青春?

目录

信号的概念

信号的种类:

 kill -l 命令可以查看信号列表

 man 7 signal 查看信号详细内容

 信号的产生

补充知识 Core Dump(转储内存)

补充知识:与信号相关的数据结构

对于不可靠信号

 接收信号

信号的处理:

阻塞信号集:

未决信号集:

信号的捕获:

 这里为了帮助理解,展了一段存在bug的代码:

运行结果:​

结语

        参考的文章

        参考的书籍


信号的概念

        在计算机科学中,信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。(摘自百度百科)

        特别强调对 异步中断 理解:因为信号是异步的,一个进程不必通过任何操作来等待信号的到达,事实上,进程也不知道信号到底什么时候到达。

信号的种类:

  kill -l 命令可以查看信号列表

 man 7 signal 查看信号详细内容

  • 每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定 义 #define SIGINT 2
  • Linux信号机制基本上是从Unix系统中继承过来的。早期Unix系统中的信号机制比较简单和原始,后来在实践中暴露出一些问题,因此,把那些建立在早期机制上的信号叫做"不可靠信号",信号值小于SIGRTMIN(在我的机器里SIGRTMIN=34,SIGRTMAX=64)的信号都是不可靠信号。这就是"不可靠信号"的来源。
  • 关于可靠信号和不可靠信号

 信号的产生

  • 按键产生,如:Ctrl+c、Ctrl+z、Ctrl+\
  • 系统调用产生,如:kill()、raise()、abort()
  • 软件条件产生,如:定时器alarm()、pause()
  • 硬件异常产生,如:非法访问内存(段错误)、除0(浮点数例外)、内存对齐出错(总线错误)
  • 命令产生,如:kill命令

上面的一些函数或命令都对百度百科进行了超链接,如果还有疑问,可以参考 《unix 环境高级编程[第10章]》

补充知识 Core Dump(转储内存)

  • wait()和waitpid(),都有一个status参数,该参数是一个输出型参数,由操作系统填充。
  • 如果传递NULL,表示不关心子进程的退出状态信息。
  • 否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。 status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图:

        

  • 关于wait()和waitpid()所返回相关的宏
  •  linux中core dump开启使用教程

我们可以通过位运算,也可以通过宏来得到我们需要的信息,具体代码如下

#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

int main(void)
{
    pid_t pid;
    if ((pid = fork()) == -1)
        perror("fork"), exit(1);
    if (pid == 0)  //child
    {
        sleep(4);
        int a=13/0; //故意写错,让程序异常退出
        exit(0xFF);
    }
    else
    {
        int st;
        int ret = wait(&st);
        // if(ret > 0 &&WIFEXITED(st) )  WIFEXITED(st)进程正常退出为真,和下面等价
        if (ret > 0 && (st & 0X7F) == 0)
        { // 正常退出
            printf("正常退出\n");
            printf("宏:st:%p child exit code:%d sig code : %d     \n",st,WEXITSTATUS(st),WTERMSIG(st));
            printf("移位运算:st:%p child exit code:%d sig code : %d\n",st,(st >> 8) & 0XFF,st & 0X7F);
            printf("core文件是否产生:%d,core dump 标志是:%d\n",WCOREDUMP(st),st & 0X80);

        }
        else if (ret > 0)
        { // 异常退出
            printf("异常常退出\n");
            printf("宏:st:%p child exit code:%d sig code : %d     \n",st,WEXITSTATUS(st),WTERMSIG(st));
            printf("移位运算:st:%p child exit code:%d sig code : %d\n",st,(st >> 8) & 0XFF,st & 0X7F);
            printf("core文件是否产生:%d,core dump 标志是:%d\n",WCOREDUMP(st),st & 0X80);
            //core会输出128,因为它刚好在第8位 ,即0X80
        }

    }
}

 运行结果:

补充知识:与信号相关的数据结构

具体一点是这样子(图片来源)

 然后我们再画简单点

对于不可靠信号

  •  每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
  • SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
  • SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。 如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。

 接收信号

信号的处理:

  1. 执行默认动作
  2. 忽略(丢弃)
  3. 捕捉(调用户处理函数)

阻塞信号集:

  • 将某些信号加入集合,对他们设置屏蔽,当屏蔽x信号后,再收到该信号,该信号的处理将推后(解除屏蔽后)。

未决信号集:

  1. 信号产生,未决信号集中描述该信号的位立刻翻转为1,表信号处于未决状态。当信号被处理对应位翻转回为0。这一时刻往往非常短暂。
  2. 信号产生后由于某些原因(主要是阻塞)不能抵达。这类信号的集合称之为未决信号集。在屏蔽解除前,信号一直处于未决状态。

介绍了这么多知识,现在我们来对信号再进行一个捕获

信号的捕获:

  • 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码 是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。当前正在执行 main函数,这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号 SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函 数,sighandler 和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控制流程。 sighandler函数返 回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复 main函数的上下文继续执行了。

 这里为了帮助理解,展了一段存在bug的代码:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>

void handler1(int sig){
    int olderrno=errno;
    pid_t child=waitpid(-1,NULL,0);
    if(child<0)
        fprintf(stderr,"    waitpid error");
    printf("    Handler reaped child %d\n",(int)child);
    sleep(1);
    printf("%s\n",strerror(olderrno));  
}

int main(){
    /*第一个参数 是信号名       SIGHLD 在一个进程终止或者停止时,将SIGCHLD信号发送给其父进程,按系统默认将忽略此信号,
                            如果父进程希望被告知其子系统的这种状态,则应捕捉此信号。
    第二参数是信号处理函数  其中 常量SIG_IGN代表忽略 SIG_DFL代表 按系统默认动作 */  
    
    //返回值 若成功,返回以前的信号处理配置; 若出错,返回 SIG_ERR
    if(signal(SIGCHLD,handler1)==SIG_ERR)   //对信号进行捕获
    
        fprintf(stderr,"signal error");
    
    //创建子进程
    int i=0;
    for(i=0;i<3;i++){
        if(fork()==0){ //child
            printf("Hello i am child %d\n",(int)getpid());
            exit(0);
        }
    }
    //父进程运行
    printf("Hi i am parent %d\n",(int)getpid());
    while(1)
        ;
    exit(0);
}

运行结果:​​​​​​​

 这里我们注意到尽管发送了3个SIGCHLD信号给父进程,但其中只有两个信号被成功接收了,因此父进程只回收了两个子进程.而子进程31288则成为了一个僵尸进程.

那么是哪里出错了呢?这段代码来源《深入理解计算机系统(第8章 图8-36)》

结语

本文也仅仅是对信号的一个浅谈,意在先树立一个大的框架,希望对读者能有所帮助,作者本人也在一路学习的过程中,很多细节由于自身经验和时间的原因,并没办法给读者细细道来,但是本文所参考的文章和书籍均会在文末放上链接,当然我也很欢迎读者如果有问题可以私信于我或在底下评论,我也会很乐意分享我的见解.

这些是我们没有细细讨论的内容,其实每一个函数都很有意思,这边再次推荐一下这本好书《UNIX环境高级编程》,当然还有《深入理解计算机系统》

 参考的文章

Linux应用与网络编程 - 随笔分类(第2页) - 浅墨浓香

Linux - 信号 | C++ 全栈知识体系

可靠信号与不可靠信号 - wsw_seu - 博客园

linux 信号处理 六(全) - 走看看

参考的书籍

 《深入理解计算机系统》

 《UNIX环境高级编程》

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

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

相关文章

qt之QCustomPlot动态更改曲线数量,单光标查看数值,选中曲线单独显示查看趋势

一、前言 本博客介绍如何由浅入深的使用一些qcustomplot的用法&#xff0c;对于开源的qcustomplot来说&#xff0c;功能实在实在是太强大了&#xff0c;如果只用于显示简单的曲线真是太浪费前人的心血了&#xff0c;本文就来介绍一些好玩的用法&#xff0c;可以实现的功能有&am…

基于javaweb的学籍管理系统计算机专业毕业论文java毕业设计开题报告

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Java项目介绍 资料获取 Java项目介绍 计算机毕业设计java毕设之基于javaweb的学籍管理系统-IT实战营_哔哩哔哩_bilibili项目资料网址: http://itzygogogo.com软件下载地址:http://itzy…

论文笔记:Template-Based Named Entity Recognition Using BART

论文来源&#xff1a;ACL 2021 Finding 论文链接&#xff1a;https://aclanthology.org/2021.findings-acl.161.pdf 论文代码&#xff1a;GitHub - Nealcly/templateNER: Source code for template-based NER 笔记仅供参考&#xff0c;撰写不易&#xff0c;请勿恶意转载抄袭…

[附源码]Python计算机毕业设计大学生扶贫创业平台Django(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

[附源码]Python计算机毕业设计SSM基于的企业人事管理系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【云计算与大数据技术】虚拟化技术、开源技术Xen、KVM、OpenVZ的讲解(图文解释 超详细)

一、系统虚拟化 系统虚拟化的核心思想是使用虚拟化软件在一台物理机上&#xff0c;虚拟出一台或多台虚拟机。步骤如下 利用虚拟化评估工具进行容量规划&#xff0c;实现同平台应用的资源整合&#xff1b; 首先采用容量规划工具决定每个系统的配置&#xff0c;利用虚拟化评估工…

【测绘程序设计】——潮汐调和分析

潮汐调和分析就是把某海面的潮位变化看成是许多分潮的余弦振动之和,根据最小二乘或频谱分析原理由实测数据计算出各个分潮平均振幅H和迟角g的过程。经典潮汐调和分析法有:Darwin分析法(频率成倍数的分潮看成一个分潮系)、Doodson分析法(周期相近的分潮看成一个分潮族)、现…

[附源码]Node.js计算机毕业设计大学生心理健康管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

redis学习笔记(三)--项目实践过程遇到的问题

怎么保证缓存和数据库数据的一致性&#xff1f; 1. 设置缓存过期时间 2. 数据的更新操作&#xff0c;先删除缓存&#xff0c;再更新数据库。如果我们先更新数据库&#xff0c;会导致其他业务线程读到缓存中的脏数据&#xff0c;所以数据库的更新操作一般是先删缓存 3. 延时双…

整流桥-交流电整直流电-桥式整流电路-电路电子-嵌入式开发-物联网开发

一、概述 本文主要讲解整流二极管的应用&#xff0c;整流的方式常见的两种为半波整流电路、桥式整流电路。本文我们将围绕桥式整流电路进行阐述。 二、电路图 在嘉立创商城&#xff0c;我们可以看到很多封装好的元件&#xff1a; 不过&#xff0c;其本质电路中有些就是桥式整流…

安卓玩机搞机技巧综合资源---MIUI14全机型首版下载链接 刷机方法 获取root步骤【十二】

接上篇 安卓玩机搞机技巧综合资源------如何提取手机分区 小米机型代码分享等等 【一】 安卓玩机搞机技巧综合资源------开机英文提示解决dm-verity corruption your device is corrupt. 设备内部报错 AB分区等等【二】 安卓玩机搞机技巧综合资源------EROFS分区格式 小米红…

Redis实战——秒杀业务优化

我们来回顾一下下单流程 当用户发起请求&#xff0c;此时会请求nginx&#xff0c;nginx会访问到tomcat&#xff0c;而tomcat中的程序&#xff0c;会进行串行操作&#xff0c;分成如下几个步骤 1、查询优惠卷 2、判断秒杀库存是否足够 3、查询订单 4、校验是否是一人一单 …

新型海上风电机组及压缩空气储能系统的建模与控制(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f468;‍&#x1f393;博主课外兴趣&#xff1a;中西方哲学&#xff0c;送予读者&#xff1a; &#x1f468;‍&a…

node+vue基于微信小程序的货物管理系统 计算机毕业设计

随着Internet的发展&#xff0c;人们的日常生活已经离不开网络。未来人们的生活与工作将变得越来越数字化、网络化和电子化。本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术、node框架和微信小程序来完成对系统的设计。…

CookieSession 学习笔记

1 Cookie 1.1 Cookie的基本使用 1 概念 客户端会话技术&#xff0c;将数据保存到客户端&#xff0c;以后每次请求都携带Cookie数据请求 2 工作流程 服务端Servlet可以将给response设置Cookie,这样浏览器接收到的数据中&#xff0c;就含有Cookie数据,下次请求时&#xff0c;会…

大数据期末课设~电商网站日志数据分析

目录 一、背景介绍... 1 二、大数据平台架构设计... 2 三、大数据平台系统设计... 7 四、数据分析与达成目标... 11 五、Spark综合编程与python可视化... 33 六、总结与体会... 50 一、背景介绍 一般情况下&#xff0c;大数据平台指的是使用了Hadoop、Spark、Storm、Fli…

可交易性(tradability)检验即协整性检验:线性关系

两个时间序列的线性关系表示为&#xff1a; 左边是两个时间序列的线性组合。是协整系数。 右边是残差序列&#xff08;residual series),表示为由两部分组成。是均衡值&#xff08;equilibrium value&#xff09;&#xff0c;是一个均值为0的时间序列&#xff0c;可以构造为均…

系统 CPU 突然飙升且 GC 频繁,如何排查

处理过线上问题的同学基本上都会遇到系统突然运行缓慢&#xff0c;CPU 100%&#xff0c;以及Full GC次数过多的问题。 当然&#xff0c;这些问题的最终导致的直观现象就是系统运行缓慢&#xff0c;并且有大量的报警。 本文主要针对系统运行缓慢这一问题&#xff0c;提供该问题…

R语言中的岭回归、套索回归、主成分回归:线性模型选择和正则化

概述和定义 在本文中&#xff0c;我们将考虑一些线性模型的替代拟合方法&#xff0c;除了通常的 普通最小二乘法。这些替代方法有时可以提供更好的预测准确性和模型可解释性。最近我们被客户要求撰写关于模型选择的研究报告&#xff0c;包括一些图形和统计输出。 主成分分析P…

19. Dropout从零代码实现以及简洁实现

1. 从零实现 要实现单层的暂退法函数&#xff0c; 我们从均匀分布U[0,1]中抽取样本&#xff0c;样本数与这层神经网络的维度一致。 然后我们保留那些对应样本大于p的节点&#xff0c;把剩下的丢弃。 在下面的代码中&#xff0c;我们实现 dropout_layer 函数&#xff0c; 该函…