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

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 

相关文章:

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

目录 什么是信号&#xff1f; 信号的产生 信号产生方式1&#xff1a;键盘 前台进程 后台进程 查看信号 signal系统调用 案例 理解进程记录信号 软件层面 硬件层面 信号产生方式2:指令 信号产生方式3:系统调用 kill系统调用 案例 其他产生信号的函数调用 1.rais…...

97_api_intro_imagerecognition_pdf2word

通用 PDF OCR 到 Word API 数据接口 文件处理&#xff0c;OCR&#xff0c;PDF 高可用图像识别引擎&#xff0c;基于机器学习&#xff0c;超精准识别率。 1. 产品功能 通用识别接口&#xff1b;支持中英文等多语言字符混合识别&#xff1b;formdata 格式 PDF 文件流传参&#xf…...

【算法】【优选算法】二分查找算法(上)

目录 一、二分查找简介1.1 朴素二分模板1.2 查找区间左端点模版1.3 查找区间右端点模版 二、leetcode 704.⼆分查找2.1 二分查找2.2 暴力枚举 三、Leetcode 34.在排序数组中查找元素的第⼀个和最后⼀个位置3.1 二分查找3.2 暴力枚举 四、35.搜索插⼊位置4.1 二分查找4.2 暴力枚…...

springboot初体验

目录 环境 controller 修改端口号 更改banner图标 运行结果 最核心的:自动装配 环境 jdk17springboot3.3.5maven3.8.2 controller controller层和启动类同级 package com.example.demo.controller; ​ import org.springframework.web.bind.annotation.RequestMapping;…...

使用kalibr_calibration标定相机(realsense)和imu(h7min)

vslam-evaluation/VINS/Installation documentation/4.IMU和相机联合标定kalibr_calibration.md at master DroidAITech/vslam-evaluation GitHub 目录 1.kalibr安装 1.1安装依赖项 1.2创建工作空间 1.3下载kalibr并编译 1.4设置环境变量 2.准备标定板 3.配置驱动和打…...

绿色工厂认定流程

以下是认定绿色工厂的一般流程&#xff1a; 编制年度创建计划 各省辖市、省直管县&#xff08;市&#xff09;会结合本地区重点产业发展现状&#xff0c;挑选一批基础条件良好、有创建意愿和条件的企业进行储备培育&#xff0c;并依据当地工业企业发展实际情况按年度制定绿色工…...

《Python游戏编程入门》注-第5章5

《Python游戏编程入门》的“Analog Clock示例程序”部分讲解了模拟时钟的实现方法。该模拟时钟可以通过时针、分针和秒针的旋转,显示当前时间,如图1所示。 图1 模拟时钟 1 绘制圆 从图1中可以看出,时钟的边缘是一个白色的圆,可以通过如图2所示的代码进行绘制。 图2 绘制圆…...

LangChain Ollama实战文献检索助手(二)少样本提示FewShotPromptTemplate示例选择器

本期是用样例来提示大模型生成我们想要的答案。即在输入中给定提示的样例&#xff0c;以及提示模板&#xff0c;然后匹配较相关的样例进行文献综述。 创建示例样本FewShotPromptTemplate 这里我用GTP-o1生成了几个回答&#xff0c;作为样本 samples [{"theme": &…...

K倍区间 C++

1230. K倍区间 - AcWing题库 一开始想到的用前缀和来做&#xff0c;时间复杂度为O(n^2),Time Limit Exceeded #include <iostream> #include <cstring> #include <algorithm> #include <cstdio>using namespace std;const int N 100010;int n,k; in…...

Linux - 弯路系列3:安装和编译libvirt-4.5.0

系统&#xff1a;Anolis8&#xff08;离线&#xff09; 目录 1、步骤2、make过程中的错误错误1&#xff1a;error: xdr_u_int64_t undeclared (first use in this function) 3、make install的错误错误1&#xff1a;/usr/bin/mkdir -p ""/usr/local/etc/libvirt/nwf…...

Jenkins插件使用问题总结

Git Push插件 插件介绍 主要是用于git推送代码到远程仓库中使用&#xff0c;插件地址 pipeline中使用 官方说明中只有一句代码gitPush(gitScm: scm, targetBranch: env.BRANCH_NAME, targetRepo: origin) 流水线语法中也做的不齐全所以一开始我老是设置错&#xff0c;导致代…...

u盘怎么重装电脑系统_u盘重装电脑系统步骤和详细教程【新手宝典】

u盘怎么重装电脑系统&#xff1f;一个u盘怎么重装电脑系统呢&#xff0c;需要将u盘制作成u盘启动盘pe&#xff0c;然后通过U盘启动盘进入pe进行安装系统&#xff0c;下面小编就教大家u盘重装电脑系统步骤和详细教程。 u盘启动是什么意思&#xff1f; U盘启动盘是一种具有特殊功…...

Sql server查询数据库表的数量

SELECT count(*) FROM sys.objects WHERE typeU --统计表数量 SELECT NAME FROM sys.objects WHERE typeU --列出表名称 或者 SELECT COUNT(*) FROM SysObjects Where XTypeU --统计表数量 SELECT Name FROM SysObjects Where XTypeU --列出表名称 --判断字…...

Linux学习笔记之软件包管理RPM与YUM

RPM包的管理 介绍 RPM&#xff08;RedHat Package Manager&#xff09;用于互联网下载包的打包及安装工具&#xff0c;它包含在某些Linux分发版中。他生成具有.RPM扩展名的文件。RPM类似Windows的setup.exe&#xff0c;这一文件格式虽然打上了RedHat的标志&#xff0c;但理念…...

15分钟学 Go 第 41 天:中间件的使用

第41天&#xff1a;中间件的使用 目标&#xff1a;学习如何在Go语言的Web服务中使用中间件 中间件&#xff08;Middleware&#xff09;是Web开发中的一种常见设计模式&#xff0c;通常用于处理请求和响应过程中的一些共通功能。比如&#xff1a;日志记录、认证授权、请求处理…...

《Python 与 SQLite:强大的数据库组合》

《Python 与 SQLite&#xff1a;强大的数据库组合》 一、Python 与 SQLite 的结合二、安装与连接&#xff08;一&#xff09;安装 SQLite 模块&#xff08;二&#xff09;连接到数据库 三、数据库操作&#xff08;一&#xff09;创建表格&#xff08;二&#xff09;插入数据&am…...

Golang | Leetcode Golang题解之第552题学生出勤记录II

题目&#xff1a; 题解&#xff1a; const mod int 1e9 7type matrix [6][6]intfunc (a matrix) mul(b matrix) matrix {c : matrix{}for i, row : range a {for j : range b[0] {for k, v : range row {c[i][j] (c[i][j] v*b[k][j]) % mod}}}return c }func (a matrix) p…...

Vue3 常用代码指南手抄,超详细 cheatsheet

一、Vue3 基础 1.1 创建 Vue3 项目 使用 Vite 创建 npm create vitelatest my-vue-app -- --template vue cd my-vue-app npm install npm run dev使用 Vue CLI 创建 npm install -g vue/cli vue create my-vue-app1.2 项目结构 my-vue-app ├── node_modules ├── pu…...

结构体是否包含特定类型的成员变量

结构体是否包含特定类型的成员变量 在C中&#xff0c;可以使用模板元编程和类型特性&#xff08;type traits&#xff09;来判断一个结构体是否包含特定类型的成员变量。这通常通过std::is_member_object_pointer类型特性来实现&#xff0c;它可以用来检查给定的成员指针是否指…...

堆排序与链式二叉树:数据结构与排序算法的双重探索

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 引言 一.堆排序 1.1 版本一 核心概念 堆排序过程 1.2 版本二 堆排序函数 HeapSort 向下调整算法 AdjustDown 向上调整算法 AdjustUp 二.链式二叉树 2.1 前中后序遍历 链式二叉树的结构 创建链式二叉树 前序遍历…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【笔记】结合 Conda任意创建和配置不同 Python 版本的双轨隔离的 Poetry 虚拟环境

如何结合 Conda 任意创建和配置不同 Python 版本的双轨隔离的Poetry 虚拟环境&#xff1f; 在 Python 开发中&#xff0c;为不同项目配置独立且适配的虚拟环境至关重要。结合 Conda 和 Poetry 工具&#xff0c;能高效创建不同 Python 版本的 Poetry 虚拟环境&#xff0c;接下来…...

生成对抗网络(GAN)损失函数解读

GAN损失函数的形式&#xff1a; 以下是对每个部分的解读&#xff1a; 1. ⁡, ​ &#xff1a;这个部分表示生成器&#xff08;Generator&#xff09;G的目标是最小化损失函数。 &#xff1a;判别器&#xff08;Discriminator&#xff09;D的目标是最大化损失函数。 GAN的训…...

华为云Flexus+DeepSeek征文 | MaaS平台避坑指南:DeepSeek商用服务开通与成本控制

作者简介 我是摘星&#xff0c;一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型&#xff0c;将实际使用经验分享给大家&#xff0c;希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 作者简介 前言 一、技术架构概览 1.1 整体架构设…...

2025-06-01-Hive 技术及应用介绍

Hive 技术及应用介绍 参考资料 Hive 技术原理Hive 架构及应用介绍Hive - 小海哥哥 de - 博客园https://cwiki.apache.org/confluence/display/Hive/Home(官方文档) Apache Hive 是基于 Hadoop 构建的数据仓库工具&#xff0c;它为海量结构化数据提供类 SQL 的查询能力&#xf…...