Linux进程信号(信号的产生)

目录

什么是信号?

信号的产生

信号产生方式1:键盘

前台进程

后台进程

查看信号

signal系统调用

案例

理解进程记录信号

软件层面

硬件层面

信号产生方式2:指令

信号产生方式3:系统调用

kill系统调用

案例

其他产生信号的函数调用

1.raise

 2.abort

信号产生方式4:软件条件

什么是软件条件?

alarm系统调用

使用

1.

2.

3.

信号的产生5:异常

示例1:

示例2:

那么os如何知道进程内部错误?

理解一下野指针的异常

Term和Core的区别


什么是信号?

信号!=信号量

信号:是一种用户,OS,其他进程向目标进程发送异步事件的一种方式。

同步和异步:

1.怎么识别信号?

识别信号是内置的。即进程识别信号时程序的内置属性。可以类比一下语言的内置数据类型(int,double)

2.信号产生后,进程知道怎么处理吗?知道  。如果没产生,进程知道怎么处理吗?也知道,因为信号的处理方法在产生之前就已经准备好了。

3.信号会被进程立即处理吗?

不一定,如果不,那么什么时候处理呢?进程会在一个合适的时候处理。

信号到来 --> <进程不立即处理,记录信号>  --> 合适的时候处理信号

4.处理信号的方法: 1.默认行为 2.忽略信号3.自定义动作

信号的产生

信号产生方式1:键盘

这有一段死循环的程序

#include <iostream>
#include <unistd.h>
int main()
{while (true){std::cout << "hello world" << std::endl;sleep(1);}return 0;
}

从键盘中输入 ctrl+c 可以前台进程杀掉前台进程。

前台进程

命令 :       ./程序名     

运行起来的是前台进程也可以用ctrl+c杀掉进程

后台进程

命令 :  ./进程名&

后台进程无法用 ctrl+c 杀死

杀掉后台进程的方法:1. fg命令将后台进程切换到前台,在ctrl+c杀掉进程。

                                    2. kill -9 pid(对应进程的pid)

方法一:

方法二: 

查看信号

kill -l  

 

man 7 signal//中可以找到相应信号的描述

signal系统调用

信号的自定义捕捉

signal的作用是捕捉signum号信号,捕捉之后,执行handler指向的函数

signum: 要捕捉的信号

#define SIGQUIT 3

handler:处理函数

案例

ctrl+\  默认终止进程

#include <iostream>
#include <unistd.h>
#include <signal.h>
void handler(int signo)
{std::cout << "signo: " << signo << std::endl;
}
int main()
{//捕捉  3)SIGQUIT信号signal(SIGQUIT, handler);while (true){std::cout << "hello world" << std::endl;sleep(1);}return 0;
}

 

ctrl+\,被捕捉不再执行默认行为(默认终止),而是将这个信号传给signo并调用自定义函数 

根据上面的案例是不是我们捕捉所有信号,那么这个死循环程序就不会被杀死了呢?

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
using func_t = std::function<void(int)>;
void handler(int signo)
{std::cout << "signo: " << signo << std::endl;
}
int main()
{//signal(SIGQUIT, handler);//捕捉信号for(int i = 1;i<=31;i++){func_t f = signal(i,handler);std::cout<<"捕捉:"<<i<<std::endl;}while (true){std::cout << "hello world" << std::endl;sleep(1);}return 0;
}

从结果上可以知道ctrl+c   ctrl+\因为被捕捉了,所以杀不掉进程,但kill -9 可以 杀掉进程,也就说明了,9)SIGKILL 不能被捕捉。

理解进程记录信号

软件层面

键盘(比如ctrl+c) -> os  -> 进程 --> 记录信号

因为os管理外设,所以键盘将信号传给os,os也管理进程,os在将信号传给进程,之后进程记录信号。

进程如何记录信号?

总结:

发送流程:键盘中的信号发送给os,os在发送给进程,修改进程对应的信号位图和其维护处理方法的函数指针数组。

 无论什么信号都是由os发送的。

os是task_struct的唯一管理者,所以只有 os有权利修改信号位图。

硬件层面

os是如何知道键盘上有数据?

轮徇(不可以,os的任务太多了)

硬件中断

冯诺依曼体系结构

在数据层面上,我们知道cpu不与外设直接打交道。而是通过存储器

但在cpu和键盘是连接的,键盘可以直接将数据交给cpu

硬件中断 --> cpu告诉os,键盘上有数据  --> 这样硬件和os就可以并行执行了

信号vs信号中断

信号是纯软甲的

信号中断是纯硬件的

信号产生方式2:指令

指令:

kill -信号 相应进程的pid

信号产生方式3:系统调用

kill系统调用

kill的作用:就是OS向(pid)进程 发送sig信号

使用代码:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
#include <sys/types.h>
int main()
{int cnt= 5;while(true){std::cout<<cnt<<std::endl;if(cnt<=0)kill(getpid(),SIGQUIT);sleep(1);cnt--;}return 0;
}

执行结果:

 kill()系统调用与kill命令的关系

kill命令行就是封装的kill()系统调用。

案例

简单实现下自己的kill

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
#include <sys/types.h>void Usage(char* argv)
{std::cout<<"Usage error: "<<argv<<" signo"<<" pid"<<std::endl;exit(1);
}
//./kill 9 pidint main(int argc,char* argv[])
{if(argc!=3){//正确使用提醒Usage(argv[0]);}int signo = std::stoi(argv[1]);pid_t pid = std::stoi(argv[2]);int ret = kill(pid,signo);if(ret<0){perror("kill");exit(2);}return 0;}

执行结果: 

其他产生信号的函数调用

1.raise

作用:让OS向调用该函数的进程返送sig信号

 2.abort

作用:让OS向调用该函数的进程返送6号信号(该进程被干掉)

 这两个函数比较简单

这两个函数都是由kill封装的,libc库函数

kill(getpid(),sig);//raise
kill(getpid(),6);//abort

信号产生方式4:软件条件

什么是软件条件?

软件条件产生信号,通常指的是在软件应用程序中,根据某些特定的条件或逻辑判断来触发或生成信号

比如:管道中,读端关闭,但写端没有关闭   这时,os回想进程发送  13)SIGPIPE信号

alarm系统调用

作用:设置一个seconds秒的闹钟,时间一到就会给调用闹钟的进程发送 14)SIGALRM信号

 alarm(条件);

里面设置的时间就相当于条件,满足条件就发送信号。

OS中维护的定时器的大概内核数据结构

 

使用

1.

#include <iostream>
#include <unistd.h>int main()
{alarm(1);int cnt = 0;while(true){//一秒打印多少次std::cout<<cnt<<std::endl;cnt++;}return 0;
}

结果:

打印了11万多次,快只能说很慢。 

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
#include <sys/types.h>int cnt = 0;
void handler(int signo)
{std::cout<<cnt<<std::endl;exit(0);
}
int main()
{alarm(1);signal(SIGALRM,handler);while(true){//std::cout<<cnt<<std::endl;cnt++;}return 0;
}

结果:计算了将近16亿次 

从上面两个程序可以看出,IO影响计算速度。

2.

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
#include <sys/types.h>int main()
{alarm(5);sleep(1);int n = alarm(0);//alarm(0)取消闹钟   n上一个闹钟剩余的时间std::cout<<n<<std::endl;return 0;
}

 3.

pause

作用:等待信号

 闹钟是一次性的发送完信号后就被取消。

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
#include <sys/types.h>
#include <vector>
using func_t = std::function<void()>;int cnt = 0;
std::vector<func_t> v;//任务void handler(int signo)
{for (auto &e : v){e();}alarm(2);cnt++;
}
int main()
{v.push_back([](){ std::cout << "我是一个日志任务" << std::endl; });v.push_back([](){ std::cout << "我是一个下载任务" << std::endl; });v.push_back([](){ std::cout << "我是一个mysql任务" << std::endl; });alarm(2);//一次性闹钟,超时后就会被取消signal(SIGALRM, handler);while (true){pause();//等待信号std::cout << "我醒来了..." << std::endl;std::cout << "cnt: " << cnt << std::endl;}
}

运行结果:

将上述逻辑中的信号变为硬件中断,就是OS的运行逻辑。

OS本质上就是一个中断处理程序 

信号的产生5:异常

示例1:

野指针

int main()
{int *p = nullptr;*p = 0;//野指针return 0;
}

Segmentation fault  段错误       

11)SIGEGV 

示例2:

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

Floating point exception   浮点异常

8)SIGFPE

 现在我们可以理解一下为什么程序会崩溃?
出现错误时,OS会向进程发送相应的信号,从而进程被干掉。

那么os如何知道进程内部错误?

比如:div 0

cpu中有状态寄存器 Eflag,Eflag中有个core dump(溢出标记为)标记为,1.cpu计算错误

                                                                                               0.无错误

验证:

#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <functional>
#include <sys/types.h>
#include <wait.h>int main()
{pid_t pid = fork();if(pid==0){//子进程int a = 10;a/=0;}else{int status;waitpid(pid,&status,0);std::cout<<"core dump: "<<((status>>7)&1)<<std::endl;std::cout<<"signo: "<<(status&0x7F)<<std::endl;}
}

 结果:

 正如所料:core dump被设为1,并向子进程发送8)SIGFPE信号

 --------------------------------------------------------------------------------------------------------------------------------

void handler(int signo)
{std::cout<<"signo: "<<signo<<std::endl;
}
int main()
{pid_t pid = fork();if(pid==0){//子进程int a = 10;a/=0;}else{int status;waitpid(pid,&status,0);std::cout<<"core dump: "<<((status>>7)&1)<<std::endl;std::cout<<"signo: "<<(status&0x7F)<<std::endl;}
}

差不多的程序如果捕获了8号信号,

结果:

os一直发送8号信号。

总结:

cpu错误 --> 谁弄坏了cpu,os发送信号杀死进程   (--> 如果捕捉了8号信号--->进程没退出--->还要调度-->还要切换执行等 -->  os不会修复Eflag中core dump(1)-->一直触发信号)

理解一下野指针的异常

 野指针的错误是由cpu中MMU错误引起的

Term和Core的区别

Trem:正常终止,不需要debug

Core:核心转储--->在当前目录下形成core文件-->进程崩溃,将进程在内存中的部分信息保存起来,方便以后调试-->一般被云服务器关闭(如果崩溃一次形成一个新的core,那么就可能把磁盘空间占满)

但当前目录下没有啊 

如何打开?

ulimit -a//查看

可以看到core file size为0;

ulimit -c 大小//改变core file size

 

readelf -S  ./sig  //查看程序elf格式

 

运行程序就可已生成core.pid的文件

如果无法生成core文件的话

在root下,输入下面的命令就可以了

echo core > /proc/sys/kernel/core_pattern
core-file core.pid//方便调试

  

如果是子进程异常呢?core的生成条件?

core dump--> 退出信号的终止动作是core && 云服务器开启core 

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

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

相关文章

【C++】STL— stack的常见用法和模拟实现

目录 1、stack的介绍 2、stack的使用 构造一个空栈 stack的简单接口应用 3、stack的模拟实现 4、栈的相关题目 4.1 最小栈 4.1.2思路 4.1.3 实现代码 4.2 栈的压入、弹出序列 4.2.2 思路 4.2.3程序实现 1、stack的介绍 在C中&#xff0c;stack是一种标准模板库&am…

神书《从零构建大模型》分享,尚未发布,GitHub标星22k!!

《从零构建大模型》是一本即将于今年10月底发布的书籍&#xff0c;github已经吸引了惊人的21.7k标星&#xff01;作者是威斯康星大学麦迪逊分校的终身教授&#xff0c;在GitHub、油管、X上拥有大量粉丝&#xff0c;是一位真正的大佬。 本书免费获取地址 在本书中&#xff0…

【深度学习目标检测|YOLO算法2】YOLO家族进化史:从YOLOv1到YOLOv11的架构创新、性能优化与行业应用全解析...

【深度学习目标检测|YOLO算法2】YOLO家族进化史&#xff1a;从YOLOv1到YOLOv11的架构创新、性能优化与行业应用全解析… 【深度学习目标检测|YOLO算法2】YOLO家族进化史&#xff1a;从YOLOv1到YOLOv11的架构创新、性能优化与行业应用全解析… 文章目录 【深度学习目标检测|YOL…

动态避障-图扑自动寻路 3D 可视化

自动寻路是机器人导航的核心技术&#xff0c;其原理主要涉及机器人与环境之间的复杂信息交互与处理。在自动寻路过程中&#xff0c;机器人依靠先进的传感器系统&#xff0c;如高清摄像头、精密激光雷达和灵敏超声波装置&#xff0c;全方位感知周围环境。这些传感器能够实时捕捉…

Docker 镜像拉不动?自建 Docker Hub 加速站 解决镜像拉取失败

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 众所周知&#xff0c;6 月份的时候&#xff0c;Docker Hub 的镜像就已经无法正常拉取&#xff0c;那会随手用 Nginx 反代了一下 Docker Hub&#xff0c;建了个自用的镜像站&#xff0c;一直用到了 9 月份&…

RabbitMQ集群搭建

RabbitMQ集群搭建 1、RabbitMQ集群1.1、默认集群模式1.1.1、为什么集群不复制队列内容和状态到所有节点? 1.2、镜像集群模式 2、默认集群模式安装前准备2.1、准备3台机器2.2、启动三台机器2.3、使用xshell 连接三台机器2.4、服务器安装erlang和RabbitMQ2.5、修改三台机器的/et…

mysql-springboot netty-flink-kafka-spark(paimon)-minio

1、下载spark源码并编译 mkdir -p /home/bigdata && cd /home/bigdata wget https://archive.apache.org/dist/spark/spark-3.4.3/spark-3.4.3.tgz 解压文件 tar -zxf spark-3.4.3.tgz cd spark-3.4.3 wget https://raw.githubusercontent.com/apache/incubator-celeb…

系统安全第七次作业题目及答案

一、 1.RBAC0 RBAC1 RBAC2 RBAC3 2.属性 身份标识 3.接入访问控制 资源访问控制 网络端口和节点的访问控制 二、 1.B 2.A 3.ABE 4.BCD 5.ABC 三、 1. 答&#xff1a;基于属性的访问控制&#xff08;ABAC&#xff09;是通过对实体属性添加约束策略的方式实现主、客体之…

【GESP】C++一级真题练习(202312)luogu-B3922,小杨报数

GESP一级真题练习。为2023年12月一级认证真题。for循环和取余计算应用。 题目题解详见&#xff1a;https://www.coderli.com/gesp-1-luogu-b3922/ 【GESP】C一级真题练习(202312)luogu-B3922&#xff0c;小杨报数 | OneCoderGESP一级真题练习。为2023年12月一级认证真题。for…

国科大现代信息检索技术第一次作业

第一次作业 题目1&#xff1a;考虑以下文档 文档名内容文档1new home sales top forecasts文档2home prices rise in june文档3increase in home sales in june文档4july new home sales rise 1、画出文档集对应的词项-文档矩阵 文档1文档2文档3文档4forecasts1000home1111…

计算机视觉实验四:特征检测与匹配

特征检测与匹配 1 角点检测算法实验 1.1 实验目的与要求 &#xff08;1&#xff09;了解及掌握角点检测算法原理。 &#xff08;2&#xff09;掌握在MATLAB中角点算法的编程。 &#xff08;3&#xff09;掌握Moravec&#xff0c;Harris与SUSAN算法的差异。 1.2 实验原理及…

十八:Spring Boot 依赖(3)-- spring-boot-starter-data-jpa 依赖详解

目录 1. 理解 JPA&#xff08;Java Persistence API&#xff09; 1.1 什么是 JPA&#xff1f; 1.2 JPA 与 Hibernate 的关系 1.3 JPA 的基本注解&#xff1a;Entity, Table, Id, GeneratedValue 1.4 JPA 与数据库表的映射 2. Spring Data JPA 概述 2.1 什么是 Spring Dat…

如何用C++代码实现一颗闪烁的爱心?

要用 C 实现爱心闪烁效果&#xff0c;我们可以使用控制台输出文本&#xff0c;并通过在控制台中刷新屏幕来模拟闪烁的效果。由于 C 本身没有类似 turtle 这样的图形库&#xff0c;操作控制台输出的方式比较简单&#xff0c;主要通过字符绘制和时间延迟来实现。 这里给出一个基…

基于美颜SDK的实时视频美颜平台开发:技术难点与解决方案

美颜SDK作为视频美颜平台的核心&#xff0c;提供了多种美颜功能。这些功能通过调整参数实现对人脸特征的优化。在架构设计上&#xff0c;美颜SDK主要包括以下几部分&#xff1a; 1.人脸检测与特征点识别&#xff1a;通过深度学习模型&#xff0c;识别人脸并标记出关键特征点&a…

web实操4——servlet体系结构

servlet体系结构 我们基本都只实现service方法&#xff0c;其余几个都不用&#xff0c; 之前我们直接实现servlet接口&#xff0c;所有的方法都必须实现&#xff0c;不用也得写&#xff0c;不然报错&#xff0c;写了又不用当摆设。 能不能只要定义一个service方法就可以&…

数据分析反馈:提升决策质量的关键指南

内容概要 在当今快节奏的商业环境中&#xff0c;数据分析与反馈已成为提升决策质量的重要工具。数据分析不仅能为企业提供全面的市场洞察&#xff0c;还能帮助管理层深入了解客户需求与行为模式。掌握数据收集的有效策略和工具&#xff0c;企业能够确保获得准确且相关的信息&a…

香港航空 m端 腾讯滑块分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

[2024最新] macOS 发起 Bilibili 直播(不使用 OBS)

文章目录 1、B站账号 主播认证2、开启直播3、直播设置添加素材、隐私设置指定窗口添加/删除 窗口 4、其它说明官方直播帮助中心直播工具教程 目前搜到的 macOS 直播教程都比较古早&#xff0c;大部分都使用 OBS&#xff0c;一番探索下来&#xff0c;发现目前已经不需要 OBS了&a…

大数据-210 数据挖掘 机器学习理论 - 逻辑回归 scikit-learn 实现 penalty solver

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

【Linux】【线程操作与同步】汇总整理

线程&#xff08;Threads&#xff09;是现代操作系统中用于并发执行的基本单元。一个进程可以包含一个或多个线程&#xff0c;每个线程都可以独立执行一段程序代码&#xff0c;共享进程的资源&#xff08;如内存&#xff09;&#xff0c;但拥有自己的栈空间和寄存器状态。下面是…