【Linux】初探信号的奥秘

news2025/2/27 4:58:01

目录

一、引入信号:

1、什么是信号:

二、前后台进程:

三、信号的处理方式:

四、键盘数据与信号:


前言:

在Linux系统编程中,信号(Signal)是一种至关重要的进程间通信机制,它允许操作系统或进程以异步方式通知目标进程某种事件的发生,例如终止进程、处理异常或触发自定义逻辑,无论是开发高并发服务器,还是调试程序中的异常行为,理解信号的原理与应用都是不可或缺的技能

对于信号的学习,我们分成四个步骤

一、引入信号:

1、什么是信号:

在我们的生活中就有许多的信号,比如当我们在网购的时候,当快递到了菜鸟驿站的时候就会给我们发一个信息,这就算是一个信号的产生,如果此时我们正在打游戏,没有时间去处理它,但是会将这个信号记住(哦,我打完这把游戏就要去拿快递)这就是对信号的保存,然后等到我真的去拿快递的时候,这就是对信号的处理

所以一个信号每时每刻都会产生,并且对于信号要做的动作并不需要立即执行,所以就需要有对信号进行保存的机制,等到合适的时候就对这个信号进行处理

在生活中有着很多很多的信号,比如说:古代的狼烟,以前的冲锋号,下课的铃声等等

那我们是怎么认识这些信号的呢?----- 当然是在生活中,被教会的,比如当看到红绿灯就需要停下来等等,当听到下课铃声的时候就知道可以休息了

那么我们回到我们的Linux中,进程也会收到很多信号,当进程收到信号的时候,和我们日常生活一样, 并不需要立刻进行处理,而是等到一个合适的时机在进行处理,那么对于这些信号,进程怎么知道要怎么处理呢?------- 这当然是创建OS的大佬程序员们在创建的时候也创建了一些信号,这样当进程收到对应的信号的时候就会进行对应的动作

所以,对于进程来说:

1、进程必须具备 识别并且能够处理信号的能力 ---- 并且如果信号没有产生也就是进程没有收到信号,也要具备能够处理,识别信号的能力(这也对应着我们的生活中,尽管此时我旁边没有红绿灯,但是我仍然知道当见到红绿灯的时候要怎样做)------ 所以信号的处理能力是属于进程内置功能的一部分

2、当进程收到一个信号的时候,进程可以不立即处理这个信号,等到合适的时候在处理

3、进程在信号产生,到开始被处理的时候,在这段时间窗口就一定会具备保存信号的能力

讲了这么多,我们先来看看在OS中有哪些信号:

如上,可以看到有62种信号,其中没有32 33号信号(具体是有历史原因的,好像是与什么什么冲突了),在信号的学习中,我们只学习前31个信号,这些信号也被叫做普通信号,对于34以后的实时信号我们不展开学习

二、前后台进程:

我们插入地了解下什么是前台进程,什么是后台进程?

在Linux系统中,前台进程后台进程是进程管理的核心概念,两者的运行方式和交互特性存在显著差异

什么是前台进程:

定义:用户通过终端直接启动并与之交互的进程 

当我们在启动进程的时候一般都是启动的前台进程,并且前台进程是能够被ctrl+c热键杀掉的,并且我们发现在输入指令的时候是没有反应的

什么是后台进程:

定义:独立于终端运行,无需用户实时干预的进程

当我们在启动进程的时候再最后加上&符号,这样我们这个进程是后台进程了

如下,我们发现当启动后台进程的时候,我们输入指令的时候居然有反应了,是互不影响的,并且用热键ctrl+c是杀不掉我们的进程的,那么怎么杀死呢?-----用9号信号kill -9 对应的进程pid

对于一个终端,我们是只允许有一个前台进程的,这是因为我们只能有一个进程和用户进行交互,如果有多个进程就会乱了,当我们启动xshell的时候就启动了一个bash这样的前台进程,当我们又运行了一个前台进程的时候,bash进程就变为后台进程了,这也就是为什么启动前台进程的时候,输入指令没有反应,因为我们输入的指令是输入给前台进程的,我们自己执行的前台进程是没有处理这些指令的代码的,所以输入指令也就没有用,当我们输入热键ctrl+c的时候,这本质上是给我们当前进程发送了2号信号来使我们的进程退出的,

那么这个时候就又有问题了,为什么我对bash这个进程进行ctrl+c的时候bash进程没有退出呢?----- 这当然是bash进程内部对这些信号进行特殊处理啦

但是可以有很多个后台进程,这个时候我们输入的指令依然是输给前台进程bash的,这也就是为什么我们启动后台进程之后输入指令依然能够显示对应的动作了,所以ctrl+c也就啥杀不死后台进程,这是因为我输入的指令发送的是前台进程bash,后台进程此时是收不到了----- 那么后台进程就无敌了吗? ----- 这显然也是不可能的,我们此时就需要使用信号,

比如kill -9 待杀死后台进程的pid即可

三、信号的处理方式:

当我们接受一个信号的时候,就会有三种处理方式

比如当我们在等红绿灯的时候:

1、默认状态,红灯停,绿灯行

2、忽略,不管红灯还是绿灯都停或者都行

3、自定义动作,比如当红灯亮的时候就唱歌,当绿灯亮的时候就跳舞

回到我们的进程中,首先学习一个接口:

void(*)(int) 表示一个函数指针,该函数接受一个int参数并返回void,其中sighandler_t就是新类型名,代表上述函数指针类型

如上,这就是对一个信号进行重定义,首先捕捉到对应的信号,再让信号进行我们重定义的动作

对于signal函数,就需要传两个参数
第一个是 要捕捉信号的序号或者对应的宏也可以
第二个参数是 指定信号处理方式,可为自定义函数、系统默认,或忽略

在了解这个函数了,我们就可以来看看ctrl+c这个热键了,这个实际上就是给我们当前进程发送2号信号,我们来验证看看:

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

using namespace std;

void myhander(int signo)
{
    cout<<"process get a signal : "<< signo << endl;
    // exit(1);
}

int main()
{
    signal(SIGINT,myhander);    
    while(1)
    {
        cout<<"i am a process "<< getpid() <<endl;
        sleep(1);
    }

    return 0;
}

其中signal第一个参数其实就是数字定义的宏,可以看看源码:

如上,这是一个进程,我们让他以前台进程的方式运行起来

如上,当运行起来后,我们使用常规的ctrl+c热键是杀不死这个进程的,这是因为ctrl+c热键本质上是向该进程发送2号信号,但是我们在代码中将2号信号的默认行为自定义为在显示器上打印一条消息了,这样ctrl+c就无法给该进程传输2号信号的默认动作了,就只能够通过别的信号,如上图右侧,通过9号信号来杀死该进程了

那么是不是我们将所有信号都重定义了,就无法杀死该进程了呢?

我们编写如下代码来看看结果:

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

using namespace std;

void myhander(int signo)
{
    cout<<"a signal was change : "<< signo << endl;
}

int main()
{

    for(int i = 1;i<=31;i++)
    {
        signal(i,myhander);
    }

    while(1)
    {
        cout<<"i am a process "<< getpid() <<endl;
        sleep(1);
    }

    return 0;
}

如上,我们将所有信号都进行捕捉,在进行验证

如上,我们先说结论:

9号信号和19号信号是不能够被捕捉的,因为这两个信号是强制用于终止/暂停进程

如果要验证可以像验证上述信号1,2,3一样

signal更深理解:

我们在使用signal函数的时候,一般放在最开始即可,因为signal只需要设置一次,在往后的生命周期中都有效(当捕捉到对应信号后就会重定义为自己新的行为),对于signal第二个参数,这只有在捕捉到信号的时候再回执行上述的函数,如果在以后的生命周期都未捕捉到对应的信号,也就不会调用上述myhander这个函数

四、键盘数据与信号:

键盘的数据是怎么输入给CPU进行处理的?ctrl+c又是怎么变成信号的?

首先,我们在冯诺依曼体系结构中了解到了:键盘是不能够直接将数据给CPU的,必须通过内存,然后在和CPU打交道,所以当键盘里面有数据了,必须是通过OS来和CPU打交道的

那么OS要怎么才能知道键盘中有数据了呢?难道没过一段时间OS都向每一个硬件都问它-----你有没有数据啊?这显然是不可能的,毕竟在我们的计算机中硬件数量很多,并且OS是不会做浪费时间的事情的,那么就需要一个解决方式:

这就需要我们的CPU了,看看上图,CPU与内存之间是不能够直接传输数据的,但是在CPU中有许多针脚,不同的硬件对应着不同的针脚,每一个针脚都有自己的编号,其功能由CPU内部的多个功能模块协同控制

当我们在键盘中按下后,控制信号通过中断单元来告诉CPU:我这键盘有数据了,你快来处理,然后CPU就会获取对应的针脚编号,然后写入寄存器中

在OS中有一个中断向量表这个概念:

中断向量表是一个函数指针,毕竟在Linux下一切皆文件,在这个表中,其成员函数指针就指向访问各种外设的方法

所以,当CPU中的一个对应的寄存器中获取到了对应的针脚编号,就会在OS中的中断向量表中对应的位置找到对应硬件的方法,执行它的读取方法就行了

这样,OS就知道要从键盘中读入数据了,此时,如果读到了ctrl+c之类的组合键,OS就会将这些转化成对应的信号发送给进程;如果读到了普通数据,就会写入对应进程的缓冲区中

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

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

相关文章

Ubuntu搭建esp32环境 配置打开AT指令集 websocket功能

1&#xff0c;搭建前提 环境搭建参考乐鑫官网给的本地编译 ESP-AT 工程方法 因为公司电脑和网络的特殊性&#xff0c;不能正确解析域名&#xff08;仅在浏览器上可以访问&#xff09; &#xff0c;所以这边访问的时候改成了ssh 未了避免使用外网困难的问题&#xff0c;这里用…

express(node ORM) 使用 Winston 记录日志 及数据库保存日志

一、安装 npm i winston npm i winston-mysql二、 配置 winston 2.1、封装 const config require(__dirname ‘/…/config/config.json’)[env]; 先判断当前是什么环境&#xff0c;如果.env中没有配置&#xff0c;就是开发环境。接着去config/config.json中读取对应的配置。…

是德科技keysight N5173B信号发生器,是一款经济高效的仪器

是德科技keysight N5173B信号发生器安捷伦N5173B信号源 是德N5173B微波模拟信号发生器&#xff0c;拥有 9 kHz 至 40 GHz 的频率覆盖范围&#xff0c;N5173B为宽带滤波器、放大器、接收机等器件的参数测试提供了必要的信号&#xff0c;是一款经济高效的仪器。 N5173B特点&…

从零到一:如何用阿里云百炼和火山引擎搭建专属 AI 助手(DeepSeek)?

本文首发&#xff1a;从零到一&#xff1a;如何用阿里云百炼和火山引擎搭建专属 AI 助手&#xff08;DeepSeek&#xff09;&#xff1f; 阿里云百炼和火山引擎都推出了免费的 DeepSeek 模型体验额度&#xff0c;今天我和大家一起搭建一个本地的专属 AI 助手。  阿里云百炼为 …

FFmpeg视频处理入门级教程

一、FFmpeg常规处理流程 #mermaid-svg-W8X1llNEyuYptV3I {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-W8X1llNEyuYptV3I .error-icon{fill:#552222;}#mermaid-svg-W8X1llNEyuYptV3I .error-text{fill:#552222;str…

C/C++ | 每日一练 (4)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 C/C | 每日一练 (4)题目参考答案基础容器序列容器std:…

蓝桥杯备考:贪心算法之矩阵消除游戏

这道题是牛客上的一道题&#xff0c;它呢和我们之前的排座位游戏非常之相似&#xff0c;但是&#xff0c;排座位问题选择行和列是不会改变元素的值的&#xff0c;这道题呢每每选一行都会把这行或者这列清零&#xff0c;所以我们的策略就是先用二进制把选择所有行的情况全部枚举…

基于 CFD 预测的机器学习第 2 部分:在 Benchmark 应用程序上使用 Stochos 预测流场

了解机器学习和 Stochos 如何彻底改变制造业的 CFD 预测。 挑战 预测复杂流体动力学场景中的流场一直是工程师和科学家面临的重大挑战。传统的计算流体动力学 &#xff08;CFD&#xff09; 方法需要大量的计算资源和时间&#xff0c;因此难以处理实时预测和大规模模拟。 此外…

批量导出数据库表到Excel

这篇文章将介绍如何批量的将多个甚至成千上万的数据库表导出为Excel文件。 准备数据 如下图是数据库里的表&#xff0c;我们需要将它们全部导出为excel文件&#xff0c;这里以SQL Server数据库为例 新增导出 打开的卢导表工具&#xff0c;新建数据库连接&#xff0c;这里以S…

力扣提升第一天

力扣提升第一天 题目链接&#xff1a;https://leetcode.cn/problems/design-memory-allocator/?envTypedaily-question&envId2025-02-25 一开始解题思路 暴力解决法 我奔着先从简单的写法做起&#xff0c;之后再想办法进行改进&#xff0c;心里已经预料到会出现超出时间…

uni-app 开发 App 、 H5 横屏签名(基于lime-signature)

所用插件&#xff1a;lime-signature 使用到 CSS 特性 绝对定位transform 旋转transform-origin transform 原点 复习一下定位元素&#xff08;相对定位、绝对定位、粘性定位&#xff09; 代码# <template><view class"signature-page"><view clas…

【Python】Python顺序语句经典题(四)

Python顺序语句经典练习题例题&#xff08;四&#xff09;。题目来源&#xff1a;Acwing 前三期合集&#xff1a;【Python】Python顺序语句经典题合集-CSDN博客 目录 1.最大值 题目描述 解题思路 AC代码 2.距离 题目描述 AC代码 3.燃料消耗 题目描述 AC代码 4.钞票…

03_pyqt5 + vlc 实现视频播放器

1.功能需求如图 按钮: 播放/暂停, 前进/后退, 视频上一个/下一个, 打开视频进度条: 视频进度条显示, 进度条拖拽, 音量控制按键控制: 1,2,3,4缩放画面大小, 2.方案选择 开发语言: python UI界面: pyqt5 qt_designed 设计ui布局 视频编码: python-vlc 方案说明: 视频解码可…

prometheus+node_exporter+grafana监控K8S信息

prometheusnode_exportergrafana监控K8S 1.prometheus部署2.node_exporter部署3.修改prometheus配置文件4.grafana部署 1.prometheus部署 包下载地址&#xff1a;https://prometheus.io/download/ 将包传至/opt 解压 tar xf prometheus-2.53.3.linux-amd64.tar.gz 移动到…

IDEA关闭SpringBoot程序后仍然占用端口的排查与解决

IDEA关闭SpringBoot程序后仍然占用端口的排查与解决 问题描述 在使用 IntelliJ IDEA 开发 Spring Boot 应用时&#xff0c;有时即使关闭了应用&#xff0c;程序仍然占用端口&#xff08;例如&#xff1a;4001 端口&#xff09;。这会导致重新启动应用时出现端口被占用的错误&a…

山东大学软件学院nosql实验三

实验题目&#xff1a; 用Java做简单查询(2学时) 实验内容 用API方式&#xff0c;做简单查询。 实验要求 在以下要求中选择至少2个&#xff0c;使用Java语言实现数据查询&#xff0c;最终把数据输出到前端界面。 &#xff08;1&#xff09;找出年龄小于20岁的所有学生 &…

零样本学习 zero-shot

1 是什么 2 如何利用零样本学习进行跨模态迁移&#xff1f; demo代码 安装clip pip install ftfy regex tqdm pip install githttps://github.com/openai/CLIP.git import torch import clip from PIL import Image# 加载 CLIP 模型 device "cuda" if torch.cuda.i…

《深度学习实战》第3集:循环神经网络(RNN)与序列建模

第3集&#xff1a;循环神经网络&#xff08;RNN&#xff09;与序列建模 引言 在深度学习领域&#xff0c;处理序列数据&#xff08;如文本、语音、时间序列等&#xff09;是一个重要的研究方向。传统的全连接网络和卷积神经网络&#xff08;CNN&#xff09;难以直接捕捉序列中…

mac下载MAMP6.8.1

因为mac的小皮面板没有php7.4了 链接&#xff1a;c9cc270e6961c17c.dmg官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘 鹅选一 附上大佬写的教程&#xff1a;MAMP PRO教程 - 牛奔 - 博客园

BUU41 [GYCTF2020]FlaskApp1【SSTI】

题目&#xff1a; 加密处没啥事&#xff0c;但是解密的地方提交{{7*7}}就会返回报错界面&#xff0c;顺便把代码也爆出来了 text_decode base64.b64decode(text.encode()) 先将字符串 text编码为字节对象&#xff0c;然后使用 base64.b64decode 函数对这个字节对象进行 Base…