信号知识详解

目录

1、信号的产生

2、core 核心转储

3、信号的保存

4、信号的处理 


        信号是linux系统提供的,让用户或进程给其他进程发送异步信息的一种方式。

常见的信号处理方式:

        1、默认行为

        2、忽略

        3、自定义

1、信号的产生

        1、kill命令

        我们可以使用命令 kill -l 查看信号,也可以使用 kill -signum pid 对指定进程发送信号。

例如:用 kill -9 将指定的死循环进程杀死。

         

        同样,我们也可以用 kill 命令发送其他信号。

        查看信号可以用 man 7 查看 man 手册。

        2、键盘

        先介绍一个系统调用:signal(),它可以改变信号的默认行为,变为自定义。

        参数:signum 为指定进程编号,想改变哪个信号的默认行为,就传哪个编号。

                   handler 为函数指针,如果进程收到了信号 signum,就执行这个函数。

        返回值:该信号的上一个处理方法。

        我们在终止进程时经常使用 ctrl + c ,这其实就是向进程发送了一个2号命令。

        ctrl + \ :这是3号命令。

证明:当我们把 2号命令和 3号命令的默认行为改成打印,使用 ctrl + c 和 ctrl + \ 能打印出来。

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

using namespace std;

void handler2(int sig)
{
    cout << "I am signal2 " << endl;
}

void handler3(int sig)
{
    cout << "I am signal3 " << endl;
}

int main()
{
    // 改变信号2和3的默认行为
    signal(2, handler2);
    signal(3, handler3);
    while(1)
    {
        ;
    }

    return 0;
}

        3、系统调用

        a、kill(),向指定进程发送指定信号

        参数: pid为要指定的进程的id,sig为要发送的信号的编号。

        返回值:成功返回0;失败返回 -1,并设置错误码。

示例:5 秒后给自己发送 2号信号终止自己

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

using namespace std;

int main()
{
    // 5 秒后给自己发送 2号信号终止自己
    int i = 0;
    while(1)
    {
        cout << "mypid is " << getpid() << " i = " << i << endl;
        if(i == 5)
        {
            kill(getpid(), 2);
        }
        ++i;
    }

    return 0;
}

        b、raise() :向调用者发送一个指定信号(谁使用这个函数就向谁发)

         参数:发送信号的编号。

        返回值:成功返回 0;失败返回非0。

示例:5 秒后给自己发送 2号信号终止自己

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

using namespace std;

int main()
{
    // 5 秒后给自己发送 2号信号终止自己
    int i = 0;
    while(1)
    {
        cout << "mypid is " << getpid() << " i = " << i << endl;
        if(i == 5)
        {
            raise(2);
        }
        ++i;
    }

    return 0;
}

        c、abort():通过发送6号信号终止自己 

         使用abort发送6号信号。

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

using namespace std;

void handler6(int sig)
{
    cout << "I am signal6 " << endl;
}

int main()
{
    // 改变信号6的默认行为
    signal(6, handler6);
    
    abort();

    return 0;
}

        d、通过alarm() 设置闹钟,时间到了就发送14号信号 

         参数:想设定的闹钟的秒数。

        返回值:如果上一个闹钟还有剩余时间,返回上一个闹钟的剩余时间,如果上一个闹钟剩余时间为0,返回0。

示例:设置一个 5 秒的闹钟,在死循环中每隔 1 秒打印 1 次信息

#include <iostream>
#include <sys/types.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

using namespace std;

int main()
{
    // 设置一个5秒的闹钟
    alarm(5);

    int i = 1;
    while(i)
    {
        cout << "mypid is " << getpid() << ", i = " << i << endl;
        sleep(1);
        ++i;
    }

    return 0;
}

2、core 核心转储

        core功能就是核心转储,将进程在内核中的核心数据,转储到磁盘中,形成core文件。通过core,我们可以定位到进程为什么退出,以及执行到哪行代码退出的。

        打开 linux 的 core 功能:

        ulimit -a  : 查看 core file size 选项,为 0 表示 core 功能关闭,不为 0 表示打开。

         ulimit -c 10240 :打开 core 功能,设置文件大小( -c 后面为文件大小 )

        我们上面讲过的 abort() 报错信号就是 有core功能的。

        如果要生成 core 文件,我们需要先停止 apport 服务:sudo service apport stop

示例代码:

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

using namespace std;

int main()
{
    int sum = 0;
    int n = 10;
    
    abort();

    for(int i = 0; i < n; ++i)
    {
        sum += i;
    }
    return 0;
}

        可以用 gdb 查看错误信息

 

3、信号的保存

        我们把实际处理信号的动作叫信号的递达(deliver)

        从产生到递达之间的状态叫做信号未决(pending)

        在进程控制块 task_struct 中,有三个表:

        block位图:阻塞位图,置为 1 表示阻塞,不处理该信号。

        pending位图:表示是否收到,置为 1 表示收到该信号。

        handler方法:序号为几的下标报存着序号为几的信号的执行方法。

        因此,我们发送信号的本质就是修改 pending 位图,阻塞信号的本质就是修改 block 位图!在信号递达时,现将 pending 位图清 0 ,再递达。

 那么我们如何对信号进行修改呢?

        未决与阻塞可以用相同的数据类型表示:sigset_t 也就是位图,系统内也存在着各种对位图进行操作的方法。

        1、sigemptyset :将所给参数中的 set 集合全置为 0.

        2、sigfillset: 将所给参数中的 set 集合全置为 1.

        3、sigaddset:将集合中的 signum 信号置为1,也就是添加该信号。

        4、sigdelset:将集合中的 signum 信号置为0,也就是删除该信号。

        5、sigismember:判断 signum 是不是 set 中的成员,也就是判断 set 中 signum 标志位是否为1.

sigprocmask可读取或更改进程的信号屏蔽字。

        参数:how可以为SIG_BLOCK表示 set 包含了我们想添加的信号屏蔽字。SIG_UNBLOCK表示 set  包含了我们想解除的信号屏蔽字。SIG_SETMASK表示直接将 set 设置为当前的信号屏蔽字。oldset表示:读取当前的信号屏蔽字。

        返回值:成功为 0 ,失败返回 -1.

其中,9号以及19号信号无法被屏蔽。

示例:屏蔽2号信号

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

using namespace std;

int main()
{
    sigset_t set;
    sigemptyset(&set);
    sigaddset(&set, 2);
    sigprocmask(SIG_BLOCK, &set, nullptr);

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

        多次输入ctrl + c(2号信号),没有终止进程 

 

4、信号的处理 

信号是什么时候被处理的呢?

        进程从内核态到用户态的时候,信号会被检查并处理。        

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

过渡与动画

单元素/组件过渡 Vue在插入、更新或者移除 DOM 时&#xff0c;提供多种不同方式的过渡效果&#xff08;一个淡入淡出的效果&#xff09; 在条件渲染&#xff08;使用v-if&#xff09;、条件展示&#xff08;使用v-show&#xff09;、动态组件、组件根节点等情形中&#xff0c;可…

【火猫DOTA2】电竞世界杯DOTA2项目将在7月份的前三周举办

1、电竞世界杯将于今年7月3日至8月25日在沙特利雅得举办。近日主办方公布了各个项目的举办时间,其中DOTA2项目将在7月份的前三周举办。转载:火猫TV资讯https://www.huomaotv.com/ 目前Falcons、XG、GG和Liquid这五支赢得了足够EPT积分的队伍已经确定直邀沙特。剩下的三个名额还…

SpringBoot集成Kafka开发

4.SpringBoot集成Kafka开发 4.1 创建项目 4.2 配置文件 application.yml spring:application:name: spring-boot-01-kafka-basekafka:bootstrap-servers: 192.168.2.118:90924.3 创建生产者 package com.zzc.producer;import jakarta.annotation.Resource; import org.spri…

MATLAB 数据输出

MATLAB 数据输出 数据导出(或输出)在 MATLAB 的意思是写入文件。MATLAB 允许您在另一个读取 ASCII 文件的应用程序中使用您的数据。为此&#xff0c;MATLAB 提供了几个数据导出选项。 您可以创建以下类型的文件- 数组中的矩形、分隔的ASCII数据文件。 击键的日记&#xff08…

Linux系统安装Redis7(详细版)

Linux系统安装Redis7 一、windows安装redis二、Linux安装Redis下载redis编辑redis7.conf文件启动redis-server服务如何关闭redis服务设置Redis开机自启动 一、windows安装redis Window 下安装 下载地址&#xff1a;https://github.com/dmajkic/redis/downloads 下载到的Redi…

6.k8s中的secrets资源

一、Secret secrets资源&#xff0c;类似于configmap资源&#xff0c;只是secrets资源是用来传递重要的信息的&#xff1b; secret资源就是将value的值使用base64编译后传输&#xff0c;当pod引用secret后&#xff0c;k8s会自动将其base64的编码&#xff0c;反编译回正常的字符…

OpenCV(一) —— OpenCV 基础

1、OpenCV 简介 OpenCV&#xff08;Open Source Computer Vision Library&#xff09;是一个基于 BSD 许可开源发行的跨平台的计算机视觉库。可用于开发实时的图像处理、计算机视觉以及模式识别程序。由英特尔公司发起并参与开发&#xff0c;以 BSD 许可证授权发行&#xff0c…

【QT学习】14.线程学习

一。线程了解 线程是计算机科学中的一个重要概念&#xff0c;它是操作系统能够进行运算调度的最小单位。线程是进程中的一个执行流&#xff0c;一个进程可以包含多个线程。与进程相比&#xff0c;线程更轻量级&#xff0c;可以更高效地利用计算机资源。 线程有以下几个特点&…

vue3+ts 原生 js drag drop 实现

vue3ts 原生 js drag drop 实现 一直以来没有涉及的一个领域就是 drag drop 拖动操作&#xff0c;研究了下&#xff0c;实现了&#xff0c;所以写个教程。 官方说明页面及实例&#xff1a;https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API 最终效果&…

企业计算机服务器中了lockbit勒索病毒如何处理,lockbit勒索病毒解密流程建议

在虚拟的网络世界里&#xff0c;人们利用网络获取信息的方式有很多&#xff0c;网络为众多企业提供了极大便利性&#xff0c;也大大提高了企业生产运营效率&#xff0c;方便企业开展各项工作业务。但随着网络技术的不断发展与应用&#xff0c;越来越多的企业开始关注企业网络数…

Flutter笔记:Widgets Easier组件库(8)使用图片

Flutter笔记 Widgets Easier组件库&#xff08;8&#xff09;&#xff1a;使用图片 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress o…

使用递归函数,将一串数字每位数相加求和

代码结果&#xff1a; #include<stdio.h> int DigitSum(unsigned int n) {if (n > 9)return DigitSum(n / 10) (n % 10);elsereturn n; } int main() {unsigned int n;scanf("%u", &n);int sum DigitSum(n);printf("%d\n", sum);return 0; …

C语言/数据结构——每日一题(合并两个有序链表)

一.前言 嗨嗨嗨&#xff0c;大家好久不见&#xff01;今天我在LeetCode看到了一道单链表题&#xff1a;https://leetcode.cn/problems/merge-two-sorted-lists想着和大家分享一下&#xff0c;废话不多说&#xff0c;让我们开始今天的题目分享吧。 二.正文 1.1题目描述 1.2题…

Javascript:Web APIs(二)

JavaScript&#xff1a;Web APIs&#xff08;一&#xff09; 在上篇文章&#xff0c;我们学习了对BOM对象的一些基本操作&#xff0c;但即使这样&#xff0c;我们也只是能通过js改变元素属性&#xff0c;而不能进行网页的交互效果和动态效果&#xff0c;这时我们就不得不提到事…

Spring Cloud——LoadBalancer

Spring Cloud——LoadBalancer 一、负载均衡&#xff08;LoadBalance&#xff09;1.LoadBalancer本地负载均衡客户端 VS Nginx服务端负载均衡区别 二、LoadBalancer1.Spring RestTemplate as a LoadBalancer Client2.编码使用DiscoveryClient动态获取所有上线的服务列表3.从默认…

QT5之lambda+内存回收机制

使用lambda需要 配置c11 所以在点.pro文件里面配置添加如下 CONFIG c11 使用到qDebug 打印包含头文件 #include<QDebug> lambda 表达式使用 代替槽如下 #include "mainwidget.h" #include<QPushButton> #include<QDebug> mainWidget::mainWid…

探索AI工具的巅峰:个人体验与深度剖析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-6.4--汇编LED驱动程序

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

省级财政收入、支出、第一、二、三产业增加值、工业增加值、金融业增加值占GDP比重数据(1978-2022年)

01、数据介绍 财政收支作为国家治理的基础&#xff0c;越来越受到社会各界的关注。同时&#xff0c;产业结构的优化与升级也是中国经济持续增长的关键因素。本数据对中国省级财政收入、支出占GDP的比重以及第一、二、三产业的增加值占GDP的比重和工业增加值占GDP的比重、金融业…

Python量化炒股的财务因子选股—质量因子选股

Python量化炒股的财务因子选股—质量因子选股 在Python财务因子量化选股中&#xff0c;质量类因子有2个&#xff0c;分别是净资产收益率和总资产净利率。需要注意的是&#xff0c;质量类因子在财务指标数据表indicator中。 净资产收益率&#xff08;roe&#xff09;选股 净资…