【信号】信号的产生

news2024/9/20 1:09:48

信号的概念

什么是信号?我们生活中的红绿灯,闹钟,外面电话等等这些都是信号,我们是怎么认识这些信号的,我们认识这些信号,并且知道这些信号的处理方法,对于进程来说,也会认识相应的信号

1.进程必须有识别和处理信号的能力,信号没有产生也要具备处理信号的一部分,处理信号的能力属于内置功能的一部分

2.进程即使没有收到信号,也知道哪些信号怎么处理

3.当进程收到某个信号的时候,可能并不会马上处理这个信号,他会保存起来,合适的时候进行处理

信号的处理方式:

a.默认动作

b.忽略

c.自定义动作 (信号的捕捉)

信号的捕捉---Ctrl+C的理解

kill -l   查看信号

 

man   7  signal   查看信号的详细信息

 往下翻就会有下面内容

我们只研究1-31号信号,1-31号信号为普通信号,其他为实时信号 

当我们在键盘按下Ctrl+c时,运行的进程就退出了

代码:

int main()
{
    
    while(true)
    {
        cout<<"hello signal"<<endl;
        sleep(1);
    }
    return 0;
}

为什么Ctrl+C可以使进程退出?Linux中,一次登录,一般会配上一个bash,每一次登录,只允许一个进程是前台进程,可以允许多个进程是后台进程,键盘输入首先是被前台进程所收到,所以Ctrl+C就被前台进程识别到,进程就退出了

假如把进程弄成后台进程

Ctrl+C是多少号信号呢? 2号

捕获信号的接口,信号本来是有默认动作的,用了这个函数可以自定义信号的动作

 

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

using namespace std;

void myhander(int signal)
{
    cout<<"process get signal: "<<signal<<endl;
}


int main()
{
    signal(2,myhander);
    while(true)
    {
        cout<<"hello signal"<<endl;
        sleep(1);
    }
    return 0;
}

当我们按下Ctrl+c时进程不退出了,并且打印了那句话,说明说明2号信号被捕获了,实行了自定义的方法,就不在实行默认的方法了

键盘数据是如何给内核的,Ctrl+C如何变成信号的?

键盘被摁下肯定是OS先知道,OS怎么知道键盘上有数据呢?难道OS会实时看看键盘有没有数据?OS也很忙的,所以不会这样弄。其实CPU也可以和外设通过硬件中断交流的,CPU上有很多针脚,这些针脚用来接收外设信号的,当键盘有数据时,键盘会通过中断单元向CPU的某个针脚发送中断号,OS会维护一张中断向量表,就是数组,内容是某个中断号对应方法的地址,CPU拿到中断号,就找到对应的方法,OS就会知道,OS就会实现对应的方法,假如是读取键盘的方法,那么OS就会从键盘读取数据到键盘缓冲区里。

不是所有的信号都可以被捕捉,都可以实行自定义动作

1-31号信号中,9号和19号不能被捕捉

信号的产生

1.键盘组合键

Ctrl+C  2号信号

Ctrl+/   3号信号

2.kill命令

kill   -signo  pid

例如:kill -9  52020

3.函数调用

kill函数,向指定进程发送几号信号

 

 mykill.cc

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

using namespace std;

void Usage(string proc)
{
    cout << "Usage:\n\t" << proc << " signum pid\n";
}

int main(int argc,char* argv[])
{
   if(argc!=3)
   {
    Usage(argv[0]);
    exit(1);
   }
   int signum=stoi(argv[1]);
   pid_t id=stoi(argv[2]);
   int n=kill(id,signum);
   if(n==-1)
   {
    perror("kill");
    exit(2);
   }

    return 0;
}

 raise函数,向调用者发送信号

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

using namespace std;

void myhander(int signal)
{
    cout << "process get signal: " << signal << endl;
}

int main()
{
    signal(2, myhander);
    int cnt = 5;
    while (true)
    {
        cout << "hello signal,mypid: " << getpid() << endl;
        cnt--;
        if (cnt == 0) raise(2);
        sleep(1);
    }
    return 0;
}

 

 abort函数,向本进程发送6号信号

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

using namespace std;

void myhander(int signal)
{
    cout << "process get signal: " << signal << endl;
}

int main()
{
    signal(SIGABRT, myhander);
    int cnt = 5;
    while (true)
    {
        cout << "hello signal,mypid: " << getpid() << endl;
        cnt--;
        if (cnt == 0) abort();
        sleep(1);
    }
    return 0;
}

运行时发现,虽然调用了自定义方法(自定义方法中没有退出) ,但是进程退出了,说明abort函数内部除了有发送6号信号,还会有让进程退出的内容

4.异常

程序异常也会发送信号使进程退出

除0错误

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

using namespace std;

int main()
{
    int a=10;
    a/=0;
    return 0;
}

 

除0异常会发送几号信号呢 ?8号信号

自定义捕获8号信号

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

using namespace std;

void myhander(int signal)
{
    cout << "process get signal: " << signal << endl;
}

int main()
{
    signal(8,myhander);
    int a=10;
    a/=0;
    return 0;
}

发现程序一直重复打印,为什么不是打印一条就退出呢?为什么呢?底层来说是因为OS一直在有这个除0错误(细节不讲了比较复杂),就一直在发8号信号,所以一直打印 

当我们用野指针异常来实现时,也是上面所对应的问题,野指针发送的是11号信号

5.软件条件

前面讲的管道,当我们读端关闭,写端打开,都没人读了,OS就发送13号信号来终止写端,这就是一个软件条件。

另一种软件条件:闹钟

给进程设置一个闹钟,时间一到闹钟就响,就会向进程发送14号信号,进程退出,返回值是闹钟的剩余时间,可以不用管

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

using namespace std;

int main()
{
    int n=alarm(5);
    while(true)
    {
        cout<<"hello signal,pid: "<<getpid()<<endl;
        sleep(1);
    }
    
}

 

 捕获14号信号

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

using namespace std;

void myhander(int signal)
{
    cout << "process get signal: " << signal << endl;
}


int main()
{
    signal(SIGALRM,myhander);
    int n=alarm(5);
    while(true)
    {
        cout<<"hello signal,pid: "<<getpid()<<endl;
        sleep(1);
    }
    
}

就打印了一条,因为只设了一个闹钟,就响一次 

Core和Term的区别

man 7 signal时,我们发现有些信号是Term,有些是Core,Term就是直接退出,Core就是退出并把进程运行信息打包到一个文件里,供我们使用,那么OS怎么知道是哪个呢?

我们在进程等待那里看到status的比特位被划分成好多部分

 剩下的一个比特位就是来存放是Core还是Term的信息的

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

using namespace std;

int main()
{
    pid_t id = fork();
    if (id == 0) // child
    {
        int cnt = 500;
        while (cnt)
        {
            cout << "i am child,pid: " << getpid() << " cnt: " << cnt << endl;
            cnt--;
            sleep(1);
        }
        exit(1);
    }
    // father
    int status = 0;
    pid_t rid=waitpid(id,&status,0);
    if(rid==id)
    {
       cout << "child quit info, rid: " << rid << " exit code: " << 
          ((status>>8)&0xFF) << " exit signal: " << (status&0x7F) <<
          " core dump: " << ((status>>7)&1) << endl; 
    }

    return 0;
}

2号信号对应的是Term,Term比特位是0

3号信号对应的是Core,但是core dump还是0,为什么?默认云服务器上的core功能是被关闭的

 打开之后,在运行程序

当前目录下就自动生成了一个文件,这个core文件里面的内容是你的代码的运行信息,怎么使用这个文件呢?  

发现这个core文件很大,所以云服务器上是默认关闭的 

打开系统的core dump 功能,进程一旦异常,OS就会把进程的运行信息转储到当前目录的一个core文件里,以后就可以通过这个文件来获取你进程的异常信息

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

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

相关文章

容器编排平台Kubernetes简介

目录 什么是K8s 为什么需要K8s 什么是容器(Contianer) K8s能做什么&#xff1f; K8s的架构原理 控制平面(Control plane) kube-apiserver etcd kube-scheduler kube-controller-manager cloud-controller-manager 小结 节点组件(Node) container runtime Pod kubelet ku…

Chrome、Edge、360及Firefox浏览器加载多个ActiveX插件的介绍

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

vc-align源码分析 -- ant-design-vue系列

vc-align源码分析 源码地址&#xff1a;https://github.com/vueComponent/ant-design-vue/tree/main/components/vc-align 1 基础代码 1.1 名词约定 需要对齐的节点叫source&#xff0c;对齐的目标叫target。 1.2 props 提供了两个参数&#xff1a; align&#xff1a;对…

成为优秀程序员-代码篇

1. 序言 刚毕业参加工作时候&#xff0c;公司正在快速扩张&#xff0c;我入职的时候组内刚刚招了一大波人&#xff0c;当时leader提出集体cr代码来拉齐团队内的编码规范&#xff0c;每当有对于相对重要改动大的项目就会集体cr代码&#xff0c;老板想法初衷是好的&#xff0c;但…

esp32 gpio 初始化不同类型的管脚,产生脉冲,发生中断

硬件&#xff1a;D4与D18 连接&#xff0c;二极管接D15与3.3v脚 图片 二极管同期性点亮&#xff0c;间隔1秒 参考esp32官网程序&#xff0c;从此程序可以看出&#xff0c;中断程序没有处理任何数据&#xff0c;只是把中断发生的事件存入队列。而用另一新线程来处理中断事务。…

GNSS CTS GNSS Start and Location Flow of Android15

目录 1. 本文概述2.CTS 测试3.Gnss Flow3.1 Gnss Start Flow3.2 Gnss Location Output Flow 1. 本文概述 本来是为了做Android 14 Gnss CTS 的相关环境的搭建和测试&#xff0c;然后在测试中遇到了一些问题&#xff0c;去寻找CTS源码(/cts/tests/tests/location/src/android/l…

Vue3-05_组件高级

背景 对组件的进一步了解,如组件之间通信等知识点&#xff0c;根据教程实现购物车功能&#xff0c;并修复原本的bug. watch 侦听器 用途 watch 侦听器允许开发者监视数据的变化&#xff0c;从而针对数据的变化做特定的操作。例如&#xff0c;监视用户名的变化并发起请求&am…

大模型AI一体机对行业的帮助

大模型AI一体机&#xff0c;如AntSKPro AI离线知识库一体机&#xff0c;是专门为企业和机构设计的集成系统&#xff0c;旨在提供高效的人工智能服务。这类一体机通常包含预训练的大型机器学习模型&#xff0c;以及必要的硬件和软件资源&#xff0c;以支持复杂的数据处理和分析任…

maven 编译构建可以执行的jar包

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

网易云音乐歌单下载器

最近要帮小朋友下载一些小学的诗词mp3&#xff0c;找了各种工具&#xff0c;还是这个好使 yun-playlist-downloader: 网易云音乐歌单下载器 特性 支持歌单 / 专辑 / 电台音质选择下载超时 / 重试再次下载默认跳过已下载部分, 使用 content-length 匹配自定义文件名下载进度显…

【代码随想录训练营第42期 Day53打卡 - 图论Part4 - 卡码网 110. 字符串接龙 105. 有向图的完全可达性

目录 一、个人感受 二、题目与题解 题目一&#xff1a;卡码网 110. 字符串接龙 题目链接 题解&#xff1a;BFS哈希 题目二&#xff1a;卡码网 105. 有向图的完全可达性 题目链接 题解&#xff1a;DFS 三、小结 一、个人感受 对于两大基本搜索&#xff1a; 深度优先搜…

JDBC:连接数据库

文章目录 报错 报错 Exception in thread “main” java.sql.SQLException: Can not issue SELECT via executeUpdate(). 最后这里输出的还是地址&#xff0c;就是要重写toString()方法&#xff0c;但是我现在还不知道怎么写 修改完的代码&#xff0c;但是数据库显示&#…

WebGL系列教程二(环境搭建及初始化Shader)

目录 1 前言2 新建html页面3 着色器介绍3.1 顶点着色器、片元着色器与光栅化的概念3.2 声明顶点着色器3.3 声明片元着色器 4 坐标系(右手系)介绍5 着色器初始化5.1 给一个画布canvas5.2 获取WebGL对象5.3 创建着色器对象5.4 获取着色器对象的源5.5 绑定着色器的源5.6 编译着色器…

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页&#xff1a;https://tangyuan96.github.io/minigpt_3d_project_page/ 代码&#xff1a;https://github.com/TangYuan96/MiniGPT-3D 论文&#xff1a;https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA&#xff0c;被ACM MM2024接收&#xff0c;只拥…

佰朔资本:9月首选行业为汽车、电子、医药生物等

5—8月商场接连调整&#xff0c;9月开端进入成绩空窗期&#xff0c;流动性和政策改动从头成为商场中心驱动力&#xff0c;风格切换先行&#xff0c;对当时的商场能够豁达一些。价值和生长风格切换的拐点开始闪现&#xff0c;生长相对价值的成绩优势开端走扩&#xff0c;美联储降…

Axure中继器介绍

中继器我们一般在处理重复性比较高的任务时&#xff0c;能让我们达到事半功倍的效果&#xff0c;中继器在整个axure中属于复杂程度比较高的功能&#xff0c;我们今天大致讲一下常用的方法即可。 一、声明一个中继器 默认展示为三行。 点击样式&#xff0c;这里我们可以添加删…

【原创】java+springboot+mysql校园二手商品交易网设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

RestTemplateRibbonOpenFeign

网络模型 OSI七层模型 RestTemplate Ribbon 在微服务中的ribbon 实现负载均衡服务间调用的三种方式 ribbon其他负载均衡策略 OpenFeign 实战

【Shiro】Shiro 的学习教程(五)之 SpringBoot 集成 Shiro + JWT

与 Spring 集成&#xff1a;与 Spring 集成 与 SpringBoot 集成&#xff1a;与 SpringBoot 集成 1、SpringBoot Shiro Jwt ①&#xff1a;引入 pom.xml&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-…

使用kubeadm手动安装K8s

本次教程安装主要基于Ubuntu 22.04&#xff0c; 使用AWS EC2服务器来部署。当然&#xff0c;AWS也有自己的AWS K8s服务&#xff0c;不过需要花费小钱钱。虽然也不是说不行&#xff0c;但手动安装下也能熟悉K8s。 1. 安装Docker 卸载旧版本&#xff1a; sudo apt-get re…