[Linux] 信号(singal)详解(一)

标题:[Linux] 信号(singal)详解

@水墨不写bug

(图片来源于网络)

目录

一、认识信号

1、认识信号

2、信号特点

3、基本概念

二、信号的产生(5种方式)

 三、信号的保存


正文开始:

一、认识信号

1、认识信号

        信号,联系生活,比如你看到钟表知道现在的时间,于是提醒自己这会儿要要干啥了;再比如,在过马路时,看到信号灯是红色,你会停下来等待,直到信号灯变绿。这都是信号的例子,其实信号简而言之,就是一种简易的信息传递方式。

2、信号特点

        随时可能产生,信号的产生是没有预告的,与你的生活是异步的。

        你能识别信号(可以想想一下,如果不能识别信号,生活会变得怎么样),并且知道得到这个信号之后该怎么做。

        当你收到信号的时候,你可能正在做更加重要的事(比如在期末考),这时需要把信号保存起来,暂不处理。

         转到OS层面:

        在进程中,信号可能随时产生,(这意味着OS需要不停的检测信号是否产生),信号的产生和进程异步。

        进程能够识别信号,并且知道得到这个信号之后该怎么做(处理信号)。

        进程可能正在做更加重要的事情,于是可能会把信号暂不处理。

综上,OS需要组织信号,并且需要在合适的时候处理信号。

3、基本概念

        信号是LINUX OS 提供的一种,向指定进程发送特定信息的方式。目的是让进程做识别和处理。

二、信号的产生(5种方式)

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

        首先可以通过   kill -l   查看所有的信号类型:

         对于不同种类的信号,OS会有不同的处理方式(后文将会有详细解释)

         2.键盘可以产生信号。

ctrl + c :SIGINT(2号信号)

ctrl + \ = | : SIGQUIT(3号信号)

(见上图)

        3.系统调用可以产生信号。

int kill(pid_t id,int sig);——kill命令的底层

void abort(void); ——产生 SIGABRT; 

        4.软件条件可以产生信号。

比如:

        管道read fd关闭,write fd还在写入,OS发送SIGPIPE (13号信号)来杀死write进程。

        alarm系统调用可以产生信号:

 

        5.异常可以产生信号。

         对于非法访问操作,被OS检测到,OS会发送信号。


OS为什么可以检测到信号?

        以发生除0错误为例,当发生除0时,CPU内部的eflag(寄存器)的溢出标记位被置1,表明本次运算的结果发生溢出,计算结果不可信。

        CPU是硬件,OS要管理硬件,于是OS会检测到CPU的这个标记位的错误信息,并通过发送信号的方式,终止发生错误的进程。

        总结:OS通过检测硬件的标记位信息,来判断是否发生了错误。


 三、信号的保存

        信号的保存和处理其实是密切联系的。信号的保存通过三张表实现的——block位图、pending位图、handler函数指针表。

 概念引入:

        信号递达:实际执行信号的过程称为信号的递达(Delivery)。

        信号未决:信号从产生到递达之间状态称为信号未决(pending)。

        信号阻塞:进程可以阻塞某一信号,意味着这个信号一旦产生,永远不递达,一直是未决状态,直到主动解除阻塞为止,才执行递达的动作。

注意:

        信号的阻塞与其是否未决无关。

        阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。


 通过查看kill -l:

 发现:

        普通信号一共31个。如果用一个位图来存储,需要31个bit位,于是Linux OS提供了一个专门的数据类型用作位图:sigset_t 。


        本章开头所说的2张位图和一张函数指针表实际就是存储在进程的task_struct中的:

         每个信号都有两个标志位分别表示阻塞(block)未决(pending),和函数指针表(handler)表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志(设置为1),直到信号递达才清除该标志(设置为0)。

        在上图的例子中:

  •         SIGHUP信号未阻塞也未产生过;当它递达时执行默认处理动作。
  •         SIGINT信号产生过,但正在被阻塞,所以暂时不能递达;虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有可能会对SIGINT进行自定义处理,进而解除阻塞之后可能会产生意想不到的结果。
  •         SIGQUIT信号未产生过;SIGQUIT产生之后,一旦产生SIGQUIT信号将被解除阻塞,它的处理动作是用户自定义函数sighandler。

到这里,我们可以总结:

        两张位图和一张函数指针数组,可以实现让进程识别信号!! 

实验:检测信号的保存 

          注意:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。如何验证(常规信号在递达之前产生多次只记一次)呢?

        通过下面的这一份实验测试,可以验证。但是你可能会对实验中使用的关于信号的函数接口有疑惑,鉴于此,我会在注释中尽可能详细注明;并在后续的文章内容中详细讲解系统的信号部分的接口的使用。       

#include <signal.h>
#include <unistd.h>
#include <iostream>using std::cout;
using std::endl;
bool loop = true;void Print(sigset_t &pending)
{for (int sig = 31; sig > 0; sig--) // 没有0号信号,信号的范围1——31,两闭{if (sigismember(&pending, sig)){cout << 1;}else{cout << 0;}}cout << endl;
}
/*一旦检测到3号信号,会走这里的处理逻辑,此时吧loop置false,使得对2号信号的处理逻辑结束。*/
void donesig2(int sig)
{cout << "get sig 3" << endl;cout << "loop = false, done sig2" << endl;loop = false;
}
void sigcb(int sig)
{loop = true;cout << "get a sig:" << sig << endl;while (loop){sigset_t pending;sigpending(&pending);//函数接口:获取目前的pending位图Print(pending);//打印出pending位图,便于观察sleep(1);signal(3, donesig2);//检测3号信号——在处理信号的同时依然可以接受并处理信号}
}int main()
{struct sigaction ac, oac;//一个结构体类型,内部存储有维护信号系统的一系列变量ac.sa_flags = 0;//暂时设为0/*sa_mask是一个sigset_t类型的位图(sigset_t是一个专门用于维护31个信号位的类型)此处这个函数的作用是把这个位图的所有位置全置0(初始化)但是这个位图目前还没有被设置进操作系统的信号位图*/sigemptyset(&ac.sa_mask);/*sa_handler是结构体内部的一个成员,是一个函数指针类型,需要用户自定义实现,也就是当进程接受到特定信号之后需要做的处理动作*/ac.sa_handler = sigcb;while (true){//这是一个和上述的结构体类型同名称的一个函数//参数:(需要屏蔽的信号,需要设置结构体类型,老的结构体类型,目的是为了保存设置之前的数据,防止用户想要撤回操作)sigaction(2, &ac, &oac);//对2号信号进行特殊处理sleep(1);cout << "I am process:" << getpid() << endl;}return 0;
}

完~

未经作者同意禁止转载

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单介绍下 VitePress 中的 vp-doc 和 vp-raw

VitePress 是一个轻量级的静态网站生成器&#xff0c;专为快速构建文档网站而设计。它是基于 Vite 和 Vue 3 构建的&#xff0c;旨在提供快速的开发体验和高效的构建过程。 存在两个需要注意的点&#xff1a;vp-doc 和 vp-raw&#xff0c;它们代表了不同的 CSS 样式类和用途&a…

服务器数据恢复—服务器raid0阵列硬盘指示灯显示黄颜色的数据恢复案例

服务器数据恢复环境&故障情况&#xff1a; 某品牌服务器上有一组由两块SAS硬盘组建的raid0阵列&#xff0c;上层是windows server操作系统ntfs文件系统。服务器上一个硬盘指示灯显示黄颜色&#xff0c;该指示灯对应的硬盘离线&#xff0c;raid不可用。 服务器数据恢复过程…

普及组集训--图论最短路径

定义&#xff1a;表示顶点u到顶点v的一条边的权值&#xff08;边权&#xff09; 最短路径算法有常见的四种&#xff1a;floyd&#xff0c;dijkstra&#xff0c;Bellman-Ford&#xff0c;SPFA 不过Bellman-Ford并不常用&#xff0c;所以本文不提&#xff1b; 重点在于dijkstr…

Linux内核ftrace的使用

文章目录 ftrace使用一、ftrace的功能与用途二、ftrace的实现原理三、ftrace的使用步骤1. 查看tracer&#xff1a;通过查看available\_tracers文件&#xff0c;了解当前内核中可用的插件追踪器2. 选择tracer3. 设置参数和过滤器4.开启追踪5. 读取追踪结果 四、ftrace的常用trac…

【笔记总结】华为云:应用上云后的安全规划及设计

一、背景和问题 数字化时代&#xff0c;随着信息技术的飞速发展&#xff0c;企业和各类组织纷纷将自身的应用程序迁移至云端。云计算凭借其诸多优势&#xff0c;如成本效益、可扩展性、灵活性以及便捷的资源共享等&#xff0c;已然成为了现代业务运营的重要支撑。 今年&#xf…

LeetCode-430. 扁平化多级双向链表-题解

题目链接 430. 扁平化多级双向链表 - 力扣&#xff08;LeetCode&#xff09; 题目介绍 你将得到一个双链表&#xff0c;节点包含一个“下一个”指针、一个“前一个”指针和一个额外的“子指针”。这个子指针可能指向一个单独的双向链表&#xff0c;并且这些链表也包含类似的特殊…

MySQL 慢查询日志记录 SQL优化 性能优化 日志查询 Explain

介绍 慢查询日志记录了所有执行时间超过指定参数(long_query_time&#xff0c;单位:秒&#xff0c;默认10秒)的所有SQL语句的日志。MySQL的慢查询日志默认没有开启&#xff0c;需要在MySQL的配置文件(/etc/my.cnf)中配置针对这些慢查询的SQL语句进行优化。 #开启慢查询开关 s…

【RL Application】语义分割中的强化学习方法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

Elasticsearch 入门

Elasticsearch安装 下载软件 Elasticsearch 的官方地址:Elastic — 搜索 AI 公司 | Elastic Elasticsearch 最新的版本是 8.16.1(截止2024.11)&#xff0c;我们选择7.8.0版本。 下载地址&#xff1a;Elasticsearch 7.8.0 | Elastic Elasticsearch 分为Linux和 Windows版本&…

Pyside6-QTableView实战

使用效果 代码 import cv2 import osfrom ui.imageQuery import Ui_DialogImageQuery from utils.log_util import log_message from utils.sys_util import create_dirfrom PySide6.QtWidgets import QApplication, QDialog, QGraphicsPixmapItem, QGraphicsScene from PySid…

Redis开发03:常见的Redis命令

1.输入以下命令&#xff0c;启动redis。 sudo service redis-server start 如果你是直接安装在WSL的&#xff0c;搜索栏搜索Ubuntu或者点击左下角Windows图表找到U那一栏&#xff0c;直接打开Ubentu&#xff0c;输入账密后&#xff0c;输入“sudo service redis-server start”…

JAVA |日常开发中常见问题归纳讲解

JAVA &#xff5c;日常开发中常见问题归纳讲解 前言一、语法错误相关问题1.1 分号缺失或多余1.2 括号不匹配1.3 变量未定义或重复定义 二、数据类型相关问题2.1 数据类型不匹配2.2 整数溢出和浮点数精度问题 三、面向对象编程相关问题3.1 空指针异常&#xff08;NullPointerExc…

ubuntu的用户使用

ubuntu系统中的常规用户登录方式 在系统root用户是无法直接登录的,因为root用户的权限过大所以其安全性比较差 在登录系统时一般使用在安装系统时建立的普通用户登录 如果需要超级用户权限: Ubuntu用户密码破解 在系统安装完成后默认grub启动等待时间为0&#xff0c;建议改…

初始Python篇(6)—— 字符串

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 目录 字符串的常见操作 格式化字符串 占位符 f-string 字符串的 format 方法 字符串的编码与解码 与数据验证相关的方法 …

38 基于单片机的宠物喂食(ESP8266、红外、电机)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52单片机&#xff0c;采用L298N驱动连接P2.3和P2.4口进行电机驱动&#xff0c; 然后串口连接P3.0和P3.1模拟ESP8266&#xff0c; 红外传感器连接ADC0832数模转换器连接单片机的P1.0~P1.…

GEE Landsat 8 可见光影像校正后下载

在遥感影像处理领域&#xff0c;Landsat 8 数据因其 30 米空间分辨率 和 多光谱波段 被广泛应用。处理这些数据时&#xff0c;研究者常常需要对数据进行裁剪、计算指数、图像增强等操作&#xff0c;以满足特定研究需求。 本文将介绍一个 Python 自动化脚本&#xff0c;使用 Goo…

Matlab Simulink HDL Coder开发流程(一)— 创建HDL兼容的Simulink模型

创建HDL兼容的Simulink模型 一、使用Balnk DUT模板二、从HDL Coder库中选择模块三、为DUT开发算法/功能四、为设计创建Testbench五、仿真验证设计功能六、Simulink模型生成HDL代码 这个例子说明了如何创建一个用于生成HDL代码的Simulink模型。要创建兼容HDL代码生成的MATLAB算法…

如何通过 JWT 来解决登录认证问题

1. 问题引入 在登录功能的实现中 传统思路&#xff1a; 登录页面时把用户名和密码提交给服务器服务器验证用户名和密码&#xff0c;并把检验结果返回给后端如果密码正确&#xff0c;则在服务器端创建 session&#xff0c;通过 cookie 把 session id 返回给浏览器 但是正常情…

像素流送api ue多人访问需要什么显卡服务器

关于像素流送UE推流&#xff0c;在之前的文章里其实小芹和大家聊过很多&#xff0c;不过今天偶然搜索发现还是有很多小伙伴&#xff0c;在搜索像素流送相关的问题&#xff0c;搜索引擎给的提示有这些。当然这些都是比较短的词汇&#xff0c;可能每个人真正遇到的问题和想获取的…

Uniad复现学习

在优云平台部署训练&#xff0c;加速训练。 关于UCloud(优刻得)旗下的compshare算力共享平台 UCloud(优刻得)是中国知名的中立云计算服务商&#xff0c;科创板上市&#xff0c;中国云计算第一股。 UCloud&#xff08;优刻得&#xff09;旗下的Compshare算力共享平台具有以下优点…