【Linux】System V IPC-进程信号

news2024/12/29 10:35:41

进程信号

  • 信号的概念
  • 信号的产生
  • 信号的种类
  • 信号的处理方式
  • 信号的注册
  • 信号的注销
  • 信号的自定义处理方式
  • 信号的捕捉流程
  • 信号的阻塞
  • 常见的程序崩溃
  • 父子进程+进程等待+自定义信号处理方式
  • volatile关键字

信号的概念

信号是一个软件中断,实际上是操作系统告诉进程需要进程执行说明动作,但是进程什么时候执行,什么时候处理,是由进程决定的,所以信号是一个软中断(意味着和强制执行某种指令的硬中断是有区别的)

在这里插入图片描述
和信号灯有些类似,实际上起着建议的作用,并没用哪个硬件强制去执行(信号灯的位置也没有人强制拉着我们不让我们走)

信号的产生

信号的产生可以分为两种:硬件产生和软件产生

硬件产生:ctrl + c, ctrl + z , ctrl + l, 它们被按下之后,分别会给进程发送的信号是 SIGINT / SIGSTOP / SIGQUIT
软件产生:kill函数,通过kill -传递的信号值 进程号

信号的种类

通过kill -l可以查看当前所有的信号
在这里插入图片描述
可以发现,当前的信号可以分为1号—>31号,34号---->64号,共62个信号,而1—>31号是属于非可靠信号(也叫非实时信号),34号---->64号是属于可靠信号(也叫实时信号),至于信号的实时和非实时有什么区别,在信号的注册和注销部分会介绍。

信号的处理方式

由操作系统给进程发送信号,进程接收到信号在进行处理时,还是需要操作系统对该信号进行处理的。
处理的方式总体可以分为三类:默认处理、忽略处理、自定义处理

默认处理方式是由操作系统定义好的,而上述62种信号总结起来一共有五种:终止,忽略,终止并产生核心转储文件、停止、继续(如果当前进程处于停止状态的话)。可以通过man 7 signal来查看
在这里插入图片描述

忽略处理:该信号为忽略处理(当子进程先于父进程退出时,子进程会给父进程发送SIGCHLD信号,而父进程接收到这个信号是忽略处理的,这使得子进程的退出状态信息没有进程回收,导致子进程变成了僵尸进程)

自定义处理:在信号的自定义处理方式会介绍

信号的注册

当一个进程接收到一个信号,这个过程称为信号的注册。
而信号的注册分为两种:非实时信号的注册和实时信号的注册。

非实时信号的注册:sig位图对应位置为1,将sigqueue节点添加到sigqueue队列中,当再次有相同的信号需要注册时,就不会再添加到sigqueue队列中了。(这样会使得多次相同的信号,最终只被添加到sigqueue队列中了一次,造成了信号的丢失)

实时信号的注册:sig位图对应位置为1, 将sigqueue节点添加到sigqueue队列中,当再次有相同的信号需要注册时,依然会被添加到sigqueue队列中。(这样的话,多次相同的信号,就会被添加到sigqueue队列中多次,不会造成信号的丢失)

如果从linux内核源码的角度理解,task_struct在linux-3.10.0-957.el7/include/linux/sched.h这个位置的1340行,
我们可以看到在task_struct中有一个模块是signal handlers,在1530行,其中有一个结构体叫做sigpending,
在这里插入图片描述

我们打开struct sigpending这个结构体后,看到有一个sigset_t这样一个类型,存放的是signal信号。
在这里插入图片描述

跳转到这个sigset_t 类型,发现也是一个结构体,其中存储的是unsigned long类型的一个位图
在这里插入图片描述

其中定义的各个信号对应的值
在这里插入图片描述

在源码中,是将信号放在sig位图中的,以bite位的方式存储,收到哪个信号就将哪一位bite位置为1。

信号的注销

注销也是需要分两种情况的:非可靠信号和可靠信号

非可靠信号,由于多个相同的信号只会被注册一次,那么当注销时,无需判断当前sigqueue队列中是否还存在这个类型的信号,直接将sig位图对应位置置为0即可。再将对应信号的sigqueue队列出队

可靠信号,需要先将对应信号的sigqueue出队,然后判断sigqueue队列中是否还有相同类型的信号,如果有sig位图不需要置0,没有才能置0;

信号的自定义处理方式

如果程序员自己不定义信号的处理方式,那么就会默认执行上述的处理方式
对于程序猿自己,也可以指定信号的处理方式,而不去执行默认的,需要使用的函数是:signal函数或者sigaction函数。

sighandler_t signal(int signum, sighandler_t handler);

signum:信号值
handler:更改为哪一个函数处理,接收一个函数指针(传递函数名即可,那个函数就是一个回调函数)
被传递的函数应该被定义为:void sighandler (int)

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

signum: 信号值
act:将信号的处理方式改为act
oldact:原来的信号处理方式

signal和sigaction函数的区别是:
在这里插入图片描述

这幅图描述了sigaction这个结构体在内核中的位置和包含的变量,在结构体中可以看到一个sa_handler,其类型是sighandler_t,这是一个函数指针类型,需要进行信号处理时,就会调用这个对象中存储的函数指针指向的函数。而signal函数就是在修改这个函数指针的指向。对于sigaction函数而言,我们修改的是struct sigaction这个结构体本身。区别就是sigaction函数包含了signal函数。

信号的捕捉流程

在这里插入图片描述

当一个进程在执行时,可能会从用户态进入到内核态,当在内核处理完成后,返回用户态之前,操作系统会判断当前是否有信号需要处理,如果有则判断当前处理方式是默认处理还是用户自定义处理,若为默认处理,则直接在内核态中调用相应的处理函数,若为自定义处理则需先返回用户态,执行自定义的信号处理函数,然后再次进入内核。执行完之后才会返回用户态继续向下执行(前提是没有需要处理的信号了)

信号的阻塞

信号的注册和信号的阻塞是分开的,互不影响。
信号被阻塞后,意味着当前这个信号暂时不被处理而已。

从内核角度理解,和sig位图相似,都是task_struct结构体内的一个位图,这个位图被称为block位图。
在这里插入图片描述
我们在内核态进行信号处理的时候,逻辑和上述的信号捕捉流程一致,只是在调用信号处理函数前会判断当前的信号是否被阻塞,如果未被阻塞,则进行处理,若被阻塞了,则暂不处理。

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

how:想让sigprocmask做什么事情:SIG_BLOCK(设为阻塞状态),SIG_UNBLOCK(设为非阻塞状态),SIG_SETMASK(用set替换原来的阻塞位图)

set:设置新的阻塞位图
oldset:老的阻塞位图


如果要设置为阻塞状态的话,将how设置为SIG_BLOCK,将对应位的set设置为1,就会和oldset进行按位或操作,这样就能将对应位置设为阻塞状态。

如果要设置为非阻塞状态,将how置为SIG_UNBLOCK,将对应位的set设置为0,就会和oldset进行按位与操作,这样就能将对应位置设置为非阻塞状态。

最终我们也可以得到一个结论,9号和19号信号是不能被阻塞的,9号信号也不能被重新定义信号处理方式

常见的程序崩溃

double free解引用空指针内存访问越界栈溢出管道破裂除0错误
SIGABRTSIGSEGV(段错误)SIGSEGV(段错误)SIGSEGV(段错误)SIGPIPESIGFPE

父子进程+进程等待+自定义信号处理方式

父进程如果需要回收子进程的退出状态信息,那么就要用wait进行进程等待,但是wait这个函数是阻塞属性的,那么就会导致父进程什么也不做,一直在等待子进程退出,那么就失去了创建子进程的目的(让程序的运行效率高)。
我们就可以使用父进程进行自定义信号的处理方式,这样就可以让父进程从等待中解放出来。

  1 #include<stdio.h>
  2 #include<sys/wait.h>
  3 #include<unistd.h>
  4 #include<stdlib.h>
  5 #include<signal.h>
  6 
  7 void signalcallback(int signum)
  8 {
  9   printf("i catch signal : %d\n", signum);
 10 }
 11 
 12 int main()
 13 {
 14   pid_t pid = fork();
 15   if(pid < 0)
 16   {
 17     perror("fork");
 18     exit(-1);
 19   }
 20   else if(pid == 0)
 21   {
 22     int count = 10;
 23     while(count--)
 24     {
 25       printf("i am child process working\n");
 26       sleep(1);
 27     }
 28     exit(2);
 29   }
 30   else{
 31     signal(SIGCHLD, signalcallback);
 32     while(1)
 33     {
 34       printf("i am father process working\n");
 35       sleep(1);
 36     }
 37   }
 38   return 0;
 39 } 

volatile关键字

作用:保证内存可见性(让cpu需要的计算数据都从内存中读取,而不会由于编译器优化程度过高导致需要的计算数据从寄存器当中读取)

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

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

相关文章

08 - 文章详情页面

文章详情页面 8-1&#xff1a;开篇 从本章开始我们要进入文章详情的页面开发。 在文章详情页面可以展示&#xff1a; 文章标题作者信息发布时间文章内容文章评论 同时你可以在这里进行&#xff1a; 作者关注文章评论文章点赞文章收藏 等操作。 基本功能大家可以进入到我…

IT知识百科:什么是暴力破解?

暴力破解是一种常见的网络安全攻击方法&#xff0c;它利用计算机程序自动尝试大量的密码组合来破解密码。这种攻击方法通常用于获取未经授权的访问权限&#xff0c;如入侵网络系统或个人账户。在本文中&#xff0c;我们将探讨暴力破解的原理、工具和防范方法。 暴力破解的原理 …

WPS表格的重复项使用方法

重复项就是指一列内容中有重复一样的值&#xff0c;或者两列数据对比后是否有重复的值&#xff0c;而在WPS表格中提供了直接标记重复值&#xff08;高度重复项&#xff09;&#xff0c;删除重复值和限制重复值在一个单元格区域中输入。 【WPS表格的高度重复项】 作用是&#…

【K8S系列】深入解析DNS

序言 世界上最幸福的事之一&#xff0c;莫过于经过一番努力后&#xff0c;所有东西正慢慢变成你想要的样子。 文章标记颜色说明&#xff1a; 黄色&#xff1a;重要标题红色&#xff1a;用来标记结论绿色&#xff1a;用来标记一级论点蓝色&#xff1a;用来标记二级论点 Kubernet…

数据挖掘——KNN算法的实现

&#x1f468;‍&#x1f4bb;作者简介&#xff1a;练习时长两年半的java博主 &#x1f4d6;个人主页&#xff1a;君临๑ &#x1f381; ps&#xff1a;点赞是免费的&#xff0c;却可以让写博客的作者开心好几天&#x1f60e; 文章目录 一、k-最近邻分类算法介绍 二、k-NN的特…

C++ 简介

C 完全支持面向对象的程序设计&#xff0c;包括面向对象开发的四大特性&#xff1a; 封装&#xff08;Encapsulation&#xff09;&#xff1a;封装是将数据和方法组合在一起&#xff0c;对外部隐藏实现细节&#xff0c;只公开对外提供的接口。这样可以提高安全性、可靠性和灵活…

soot中存在的主要对象、soot的执行流

soot代码分析框架的基础知识&#xff08;二&#xff09;_soot 代码分析_小作坊中搬砖的博客-CSDN博客 Soot中的结构 本篇内容简单概括一下&#xff1a;soot中存在的主要对象、soot的执行流。 Soot中提供了几种对象&#xff0c;分别是&#xff1a;Scene、SootClass、SootMetho…

如何在 Windows WSL 上安装 k3s (Kubernetes / k8s)

WSL&#xff0c;全称Windows Subsystem for Linux&#xff0c;是微软在Windows 10操作系统上开发的一种运行Linux应用程序的子系统。它允许用户在Windows系统中直接运行Linux命令行工具和应用程序&#xff0c;无需双重引导或虚拟机。 相比虚机&#xff0c;WSL提供了更加高效、…

能量密度的必要性:城市比乡村具有更高的能量密度

文章目录 引言I 人口密度1.1 人口密度太低对于经济的发展的不利因素1.2 足够的人口密度带来的好处1.3 乌鲁克城II 农耕文明和商业文明2.1 农耕文明2.2 商业文明III 有效掌握动力的文明处于优势3.1 苏美尔人- 轮子&风能的利用3.2 英国人- 以蒸汽机为代表的工业革命引言 文明…

LeetCode——根据二叉树创建字符串与二叉树的最近公共祖先

606. 根据二叉树创建字符串 给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 “()” 表示&#xff0c;转化后需要省略所有不影响字符串与原始二…

C#医院体检管理系统源码,PEIS源码,C/S结构 oracle数据库

PEIS体检管理系统源码&#xff0c;医院体检系统源码PEIS源码&#xff0c;商业级源码 本套PEIS医院体检管理系统源码采用C/S结构&#xff0c;前台开发工具为Vs2012&#xff0c;后台数据库采用oracle大型数据库。 核心功能有&#xff1a;体检档案的录入、体检报告的输出、体检档…

震惊!ChatGPT可以用来炒股?

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 ChatGPT让我们见识了大模型技术的强大潜能&#xff0c;激发了市场的热情。 然而&#xff0c;对于大多数人而言&#xff0c;最关心的问题很可能是——如何用ChatGPT赚钱。谈到赚钱&#xff0c;最直接的就是金融&#xff0c;其…

word插入页码

word如何设置域http://zhidao.baidu.com/question/382747671/answer/3053706353 1、首先&#xff0c;我们打开我们电脑上面的word&#xff0c;然后我们点击插入。 2、然后我们点击工具栏中的文档部件&#xff0c;弹出的界面&#xff0c;我们点击域。 3、弹出的界面&#xff0c…

iOS设备和蓝牙模块连接基础知识

iOS设备和蓝牙模块连接基础知识 一&#xff1a;iOS连接外设的几种方式 如图下面几种方式&#xff1a; CoreBluetooth和ExternalAccessory&#xff0c;两个框架&#xff0c;基本上是蓝牙设备与iOS设备连接的方式 有图可知&#xff0c;EAP要MFi认证&#xff0c;要求设备的设计理…

pywebview搭建、运行、打包白屏

1、禁用微软商店引流 点击开始菜单输入管理应用执行别名搜索系统设置&#xff0c;将该列表划到最底部&#xff0c;找到python.exe和python3.exe&#xff0c;将其设置为关闭状态 这是微软搞的狗皮膏药&#xff0c;强制型环境变量 2、配置Python环境 1.考虑版本管理&#xff…

Docker原理与镜像管理

目录 一、虚拟化概述 虚拟架构 1、寄居架构 2、原生架构 两者的区别 虚拟化产品 虚拟化类型 二、Docker概述 Logo含义 Docker的设计宗旨 Docker与虚拟机的区别 Docker核心概念 镜像 容器 仓库 Docker Engine&#xff08;引擎&#xff09; Docker运行的原理 d…

组合设计模式解读

目录 问题引进 传统方案解决学校院系展示存在的问题分析 组合模式基本介绍 基本介绍 组合模式原理类图 对原理结构图的说明-即(组合模式的角色及职责) 应用实例 组合模式的注意事项和细节 问题引进 看一个学校院系展示需求 编写程序展示一个学校院系结构&#xff1a;需…

浏览器加 buff 指南-【超实用的浏览器工具】

今天这篇博客&#xff0c;说一说浏览器以及加 buff &#xff0c;先说浏览器&#xff1a;地址&#xff1a;https://www.xduoyu.com/&#xff0c;里面的工具让你的浏览器变装为技术人员的专属利器。这里还要表扬一下&#xff0c;官网的宣传页做的越来越专业了&#xff0c;还打造了…

好的台灯和差的台灯的区别?盘点高品质的护眼台灯品牌

简单来说&#xff0c;好的台灯使用20分钟不会眼疲劳&#xff0c;可差的台灯使用10分钟就眼干涩、不舒服了。 这些年的LED灯具都做得非常成熟&#xff0c;台灯也是LED灯具&#xff0c;在频闪、蓝光、显色指数、均匀度等各种指标都将眼睛保护的很好&#xff0c;采用特殊的光学技…

Thinkphp+vued大学生租房管理系统mysql校园房屋租赁网站系统

学生租房管理系统是计算机技术和网络迅速发展的一个大学生租房信息应用解决方案。大学生租房平台将Internet网络技术与现代管理观念相融合&#xff0c;针对信息技术的特点对大学生租房平台进行规划和重构&#xff0c;对大学生租房信息流进行优化及合理配置&#xff0c;生成动态…