当前位置: 首页 > news >正文

linux之进程信号

目录

生活例子--提炼基本结论

  信号概念的基本储备

 信号处理

信号产生

信号保存

信号处理


前提知道信号与信号量没有任何关系就比如老婆和老婆饼一样;

生活例子--提炼基本结论

1.  比如说平时定闹钟,我今晚十一点睡觉,睡觉之前定个八点的闹钟,那么在闹钟响了在客观上就是闹钟给我发了个信号;

2.  平时我们过红绿灯,红灯亮了,红黄灯就给我发出一个信号那么此时我就应该等一等 ,绿灯亮了我就可以走了;

3.  在古代我是一个大头兵,远远望见狼烟升起,那么就知道有人要冲出来了就知道要打仗了;

4.  在家里呢,考试没考好,回家的时候发现爸妈往沙发上一座并且脸色阴沉给你传递了一个不好的信号,你此时就知道完蛋了;

1.  信号在生活中随时可以产生

           你也不知道哪一天被分手了等叫做   信号的产生和我是:异步的

2.  你能认识这个信号(红绿灯,狼烟点起,脸色等)

3.  我们知道信号产生了,也知道信号触发了该怎么处理(红绿灯亮了我们知道该怎么办)

           我们把23叫做    你能识别并处理这个信号

4.  我们可能正在做着更重要的事情,只能把到来的信号暂不处理

(就比如我点了个外卖,点好后我在打游戏,突然外卖小哥电话打来了,我就意识到了外卖到了。说明了我能认识外卖小哥电话这个信号,外卖小哥电话产生了我也知道该怎么处理下去拿外卖,但我此时正在做其他的事,那我可能说放楼下或者不管电话)

注意将上述的我换成进程即可;进程识别,进程处理,进程暂不处理等

  信号概念的基本储备

信号:linux系统提供的一种向指定进程发送特定事件的方式;

比如说我要向进程发送9号信号表明要终止进程,比如说要发送19号要暂停一个信号等;

进程收到对应的信号后要对信号做识别和处理;

 信号产生是异步的:信号的到达不依赖于进程的执行状态,可能在进程执行的任何时刻被接收。

 信号处理

 信号的默认动作: 

 进行自定义处理,不想执行默认动作,想让进程收到信号后执行我设定的方法: 



 

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>void hander(int sig)
{ // 这个sig就是传递过来的信号编号std::cout << "get a sig: " << sig << std::endl;
}int main()
{// 对信号的自定义捕捉,我们只要捕捉一次,后续一直有效signal(2, hander); // 对2号信号自定义,名字hander随便起//将来收到2号信号后,未来2号信号将以参数形式传递给hander方法//如果一直不产生2号信号,那么hander就永远不会被调用//我们也可以对更多的信号进行捕捉signal(3, hander);signal(4, hander);signal(5, hander);while (true){std::cout << "hello nihao,pid: " <<getpid()<< std::endl;sleep(1);}return 0;
}

  注意:2 SIGINT代表是终止进程,我们平常用的ctrl+c-----给目标进程发送2号信号,所以使用ctrl+c在命令行中使用直接结束进程

  注意:3 SIGQUIT代表是退出进程,我们平常用的ctrl+\-----给目标进程发送3号信号,所以使用ctrl+\在命令行中使用直接退出进程

信号产生

1.  通过kill命令,向指定的进程发送特定的信号

2.  键盘可以产生信号!比如ctrl+c或者ctrl+\

3.  系统调用 

int kill(pid_t pid, int sig);          

kill(getpid(),xxx)==int raise(int sig);给自己发信号,但raise不如kill重要

void abort(void);表示用于立即异常终止当前程序的执行。。abort() 函数会导致程序异常终止。它通常用于在遇到无法恢复的错误时强制停止程序,并产生一个 SIGABRT 信号。

无论用户使用kill命令还是使用键盘打命令还是用户程序调用,但最终发送信号的还是os。

因为发送信号的本质就是修改pcb的位图,只有os才有资格修改; 

 如果我把所有信号都捕捉了呢?

4.  软件条件 

就比如管道的时候,读端关闭而写端一直写---就会发送13 SIGPIPE。在软件层面上因为某些条件不满足,向你的进程发送信号;

这时候介绍alarm函数:

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>int main(){int cnt=1;alarm(1);//设定一秒的闹钟  一秒后收到SIGALRM信号while(true){std::cout<<"cnt: "<<cnt<<std::endl;cnt++;}return 0;
}

验证IO很慢:

只最后进行IO,不用循环里每次都IO,减少IO次数;

理解闹钟: 

就比如电脑关机了两天,断电断网,但是两天后把电脑打开后右下角的时间还是准确的。

这是因为我们的电脑,在主板上还有一个东西叫纽扣电池,很小,但他一直在维持电脑的时间的,虽然我们关机了,但是电脑中依旧有个电池有电。

闹钟的返回值: 


闹钟设置一次就默认触发一次;

5.  异常 

 除0崩溃:

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>void hander(int sig)
{std::cout << "get a sig: " << sig << std::endl;
}int main()
{signal(8,hander);while (true){std::cout << "pid: " << getpid() << std::endl;sleep(2);int a = 10;a /= 0;// int *p=nullptr;// *p=100;}
}

发现循环打印

一直在打印,捕捉到了,说明就是发送了信号。通过man 7 signal查到8号默认终止

野指针崩溃:

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>void hander(int sig)
{std::cout << "get a sig: " << sig << std::endl;
}int main()
{signal(11, hander);int *p = nullptr;*p = 100;while (true){std::cout << "pid: " << getpid() << std::endl;sleep(2);// int a = 10;// a /= 0;}
}

发现也是循环打印,但是没在循环里面也循环打印

通过man 7 signal查到11号默认终止

 崩溃了为什么会退出?因为发送的信号默认是终止进程;

可以不退出么?可以,捕捉了异常,但不建议,推荐终止进程;

程序上出现异常最终会体现在硬件上,硬件上的问题又会被os识别到; 

信号保存

信号处理

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • ETCD学习使用
  • 解决跨域问题的方法
  • 关于模型外推能力的论文
  • 深入探秘 WorkManager:Android 异步任务管理的强大工具
  • 面试真题 | 小红书-C++引擎架构
  • vscode 代码格式setting设置
  • Java语法-类和对象(上)
  • java jdk8内存序列化为xml
  • C语言 | Leetcode C语言题解之第416题分割等和子集
  • 一个示例了解什么是 API 集成
  • 设计模式之责任链
  • CSS基本概念以及CSS的多种引入方式
  • CSS调整背景
  • 使用 HFD 加快 Hugging Face 模型和数据集的下载,解决443报错
  • PHP 递归遍历目录
  • [译] 怎样写一个基础的编译器
  • Android系统模拟器绘制实现概述
  • canvas绘制圆角头像
  • Java面向对象及其三大特征
  • Map集合、散列表、红黑树介绍
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • vue-router 实现分析
  • Webpack 4x 之路 ( 四 )
  • 老板让我十分钟上手nx-admin
  • 离散点最小(凸)包围边界查找
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 硬币翻转问题,区间操作
  • elasticsearch-head插件安装
  • ‌移动管家手机智能控制汽车系统
  • $.ajax,axios,fetch三种ajax请求的区别
  • (¥1011)-(一千零一拾一元整)输出
  • (06)Hive——正则表达式
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (javascript)再说document.body.scrollTop的使用问题
  • (pytorch进阶之路)扩散概率模型
  • (定时器/计数器)中断系统(详解与使用)
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)ssm教师工作量核算统计系统 毕业设计 162307
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (四)Controller接口控制器详解(三)
  • (五)c52学习之旅-静态数码管
  • (转)ABI是什么
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .[hudsonL@cock.li].mkp勒索加密数据库完美恢复---惜分飞
  • .NET delegate 委托 、 Event 事件,接口回调
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .net解析传过来的xml_DOM4J解析XML文件
  • .NET中winform传递参数至Url并获得返回值或文件
  • .pyc文件是什么?
  • @Builder用法
  • @FeignClient 调用另一个服务的test环境,实际上却调用了另一个环境testone的接口,这其中牵扯到k8s容器外容器内的问题,注册到eureka上的是容器外的旧版本...