Liunx进程信号

进程信号

  • 进程信号
    • 什么是信号
    • liunx信号种类
  • 前后台进程
    • 前后台进程的概念
  • 进程信号的产生
    • 键盘产生
  • 阻塞信号
    • 信号的捕捉
      • 用户态和内核态
    • 信号的捕捉函数

进程信号

什么是信号

信号是Unix、类Unix以及其他POSIX兼容的操作系统中进程间通讯的一种有限制的方式。它是一种异步的通知机制,用来提醒进程一个事件已经发生。当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。

liunx信号种类

Liunx中如何查看信号种类:
在这里插入图片描述

信号名称信号编号描述
SIGHUP1终端挂起或控制进程结束
SIGINT2终止进程(由键盘输入 Ctrl+C 产生)
SIGQUIT3终止进程并生成核心转储文件(由键盘输入 Ctrl+\ 产生)
SIGILL4非法指令
SIGTRAP5跟踪陷阱
SIGABRT6终止进程并生成核心转储文件(由调用 abort() 函数产生)
SIGBUS7非法地址访问
SIGFPE8浮点异常
SIGKILL9无条件终止进程
SIGUSR110用户定义的信号1
SIGSEGV11无效的内存引用
SIGUSR212用户定义的信号2
SIGPIPE13管道破裂
SIGALRM14定时器超时
SIGTERM15请求终止进程(默认终止信号)
SIGSTKFLT16协处理器栈错误
SIGCHLD17子进程状态改变
SIGCONT18继续被暂停的进程
SIGSTOP19停止进程
SIGTSTP20暂停进程(由键盘输入 Ctrl+Z 产生)
SIGTTIN21后台进程尝试读取控制终端
SIGTTOU22后台进程尝试写控制终端
SIGURG23套接字的紧急情况
SIGXCPU24CPU 时间限制超时
SIGXFSZ25文件大小限制超过
SIGVTALRM26虚拟定时器超时
SIGPROF27分析计时器超时
SIGWINCH28窗口大小调整
SIGIO29异步 I/O 事件
SIGPWR30电源故障
SIGSYS31非法系统调用

前后台进程

前后台进程的概念

前台进程在命令行操作时,只能有一个,后台进程可以有多个。

接下来我们启动一个后台进程。
我们创建一个后台进程,并且让他给文件不停的写入。
在这里插入图片描述
此时我们查看 log.txt
在这里插入图片描述
可以看到。进程在后台运行,那我们如何查看呢?
jobs 就可以看到
在这里插入图片描述
如何杀掉后台进程呢? 我们需要把fg后台放到前台,然后退出。
在这里插入图片描述
下面附上常用命令:

快捷键描述
Ctrl+C终止并退出前台进程,回到Shell
Ctrl+Z暂停前台命令执行,放到后台,回到Shell
jobs查看当前在后台执行的命令
&在后台执行命令
fg N将进程号码为N的命令放到前台执行
bg N将进程号码为N的命令放到后台执行

进程信号的产生

键盘产生

用户在Linux下执行一个前台进程,然后使用ctrl+c操作,会直接终止掉该前台进程。这是因为用户按下ctrl+c,这个键盘输入产生一个硬件中断,被OS获取,解释成信号,发送给目标前台进程,前台进程因为收到信号,进而引起进程退出。

ctrl+c组合键只能终止掉前台进程,对后台进程无效。这时我们可以使用kill -9指令来该终止进程
在这里插入图片描述
crtl+c的信号本质就是2号信合
在这里插入图片描述
接下来我们通过一个函数验证这个事:
在这里插入图片描述
在这里插入图片描述
像进程发送2号信合,运行新程序。
查看进程退出码:echo $?
在这里插入图片描述

························································································································································

阻塞信号

信号的常见分类:

  1. 实际执行信号的处理动作,称为信号递达(Delivery)。
  2. 信号从产生到递达之间的状态,称为信号未决(pending)。
  3. 进程可以选择阻塞(Block)某个信号。
    被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。

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

在内核中的表示
未决信号,就是你的进程已经接收到了信号了,只是还没被信号处理函数处理的那些信号。

特别说明:虽然未决信号的定义是上面这样,但是这里我们需要更加具体一点,未决信号特指进程收到且被阻塞的信号。

在这里插入图片描述

  1. 每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。
  2. 在上图中,SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
  3. 在上图中,SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会在改变处理动作之后再接触阻塞。
  4. 在上图中,SIGQUIT信号未产生,正在被阻塞,不能执行自定义函数。
  5. 处理动作包括默认、忽略以及自定义。
    sigset_t
    根据信号在内核中的表示方法,每个信号的未决标志只有一个比特位,非0即1,如果不记录该信号产生了多少次,那么阻塞标志也只有一个比特位。

sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态。

在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞。 在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask)

信号集操作函数
sigset_t类型对于每种信号用一个bit表示“有效”或“无效”,至于这个类型内部如何存储这些bit则依赖于系统的实现,从使用者的角度是不必关心的,使用者只能调用以下函数来操作sigset_t变量,而不应该对它的内部数据做任何解释,比如用printf直接打印sigset_t变量是没有意义的。

#include <signal.h>int sigemptyset(sigset_t *set);// 对指定信号集进行清空。int sigfillset(sigset_t *set);//对指定信号集进行置1int sigaddset(sigset_t *set, int signum);//将指定的信号signum添加到信号集中 也就是置1int sigdelset(sigset_t *set, int signum);//将指定的
信号signum在信号集中置0
int sigismember(const sigset_t *set, int signum); //判定signum是否为1 

接下来介绍重要函数:

#include<signal.h>int sigprocmask(int how,const sigset_t *set,__sigset_t *oset);//若返回成功则返回0.

how参数

选项含义
SIG_BLOCK设置包含了我们希望添加到当前信号屏蔽字的信号,相当于 `mask = mask
SIG_UNBLOCK设置包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于 mask = mask & ~set
SIG_SETMASK设置当前信号屏蔽字为 set 所指向的值,相当于 mask = set

接下来我们屏蔽2号信合!
在这里插入图片描述

#include<iostream>
#include<unistd.h>
#include<signal.h>
using namespace std;void handler(int signo)
{cout<<"handler get signo:"<<signo<<endl;
}int main()
{signal(2,handler);//set==block oset== oblocksigset_t set,oset;sigemptyset(&set);//初始化sigemptyset(&oset);sigaddset(&set,2);//设置对2号信合屏蔽 但是并没有设置进入系统sigprocmask(SIG_BLOCK,&set,&oset);while(1){cout<<"mypid:"<<getpid()<<endl;sleep(1);}return 0;
}

#############################

设置完成后,我们对代码进行编译。

在这里插入图片描述

可以发现我对2号信合免疫了。

pending未决队列表的获取:

sigpending

读取当前进程的未决信号集,通过set参数传出来。


接下来我们以一个综合案例操作:

  1. 屏蔽2号信合 这个屏蔽是阻塞
  2. 通过sigpending查询2号信合
  3. 发送2号信合。
    在这里插入图片描述
    我们可以看到,发送2号信合,此时2号信合处于未决状态。
    在10次后,我们取消对2号的阻塞
    在这里插入图片描述

信号的捕捉

信号的捕捉发生在用户态和内核态的互相转换中,首选我们必须先知道什么是用户态,什么是内核态。

用户态和内核态

在这里插入图片描述

①OS在不在内存中被加载呢? ?——在 无论进程怎么切换,我们都可以找到内核的代码和数据,前提是你只要能够有权利访问!

②当前进程如何具备权利 访问这个内核页表乃至访问内核数据呢?——要进行身份切换。
进程如果是用户态的——>只能访问用户级页表 0~3G
进程如果是内核态的——>访问内核级和用户级的页表 3~4G 、③我怎么知道我是用户态的还是内核态的呢?
CPU内部有对应的状态寄存器CR3, CR3有比特位标识当前进程的状态 0:内核态,3:用户态

④0—>3
用户态切到内核态的情况:1.系统调用的时候。2.时间片到了,进程间切换。3.其他等等。执行完毕就继续切回用户态。即:程序运行从用户态切换到内核态的操作:中断/异常/系统调用,例如

    <1> 整数除以零操作会导致用户态—>内核态:因为会导致程序异常(分母不能为0)<2> sin()函数调用操作不会切换状态,因为库函数并不会引起运行态的切换<3> read 系统调用操作会导致用户态—>内核态:符合系统调用接口

⑤内核态vs用户态 内核态可以访问所有的代码和数据——内核态具备更高权限 用户态只能访问自己的

⑥我们的程序,会无数次直接或者间接的访问系统级软硬件资源(管理者是OS),本质上,你并没有自己去操作这些软硬件资源,而是必须通过OS-

无数次的陷入内核(1.切换身份3->0 2.切换页表,切到内核级页表)->调用内核的代码->完成访问的动作->结果返回给用户(1.切换身份0->3 2. 切换页表,切到用户级页表)->用户得到结果

⑦while(1);死循环进程普通程序会身份切换吗? —>也会陷入内核,来回切换身份 —>你也有自己的时间片
—>时间片到了的时候->OS收到中断信息,把进程从cpu移走,进程切到内核态,更换内核级页表 —>保护上下文,执行调度算法
—>选择了新的进程 —>恢复新进程的上下文 —>用户态,更换成用户级页表 —>CPU执行的就是新进程的代码!

重点: 用户态到内核态的两种切换场景:

  1. 除0错误。操作系统互捕捉这个错误,并且切换到内核态
  2. 使用系统调用函数接口,会从用户态切换到内核态。

自定义捕捉信号的处理过程
在这里插入图片描述
这个图是对自定义信号的处理,以及检测时机。

  1. 调用系统调用函数,此时用户态切换内核态
  2. 此时操作系统处理完之后,检测处理信号
  3. 信号为自定义信号处理方式 ,内核态不处理用户态代码
  4. 处理完成,继续返回内核态
  5. 从内核态返回用户态

在这里插入图片描述
正无穷记忆法!!!

信号的捕捉函数

  1. signal 常用捕捉函数
  2. sigaction 信号捕捉函数
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 

该函数需要将方法写入结构体中。

struct sigaction {  void     (*sa_handler)(int);  void     (*sa_sigaction)(int, siginfo_t *, void *);  sigset_t   sa_mask;  int        sa_flags;  void     (*sa_restorer)(void);  
};

**sa_handler:**这是一个指向函数的指针,当接收到指定的信号时,这个函数会被调用。如果设置为 SIG_IGN,则忽略该信号;如果设置为 SIG_DFL,则使用默认的信号处理行为。
**sa_mask:**这是一个信号集,用于在信号处理函数执行期间阻塞的信号。这确保了在处理一个信号时,不会受到其他信号的干扰。 也就是说,阻塞二号信号的
其他的几个参数并不需要我们了解。

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

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

相关文章

【MySQL】:深入解析多表查询(上)

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; MySQL从入门到进阶 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一. 多表关系1.1 一对多1.2 多对多1.3 一对一 二. 多表查询概述2.1 概述2.2 分类…

基于Springboot的航班进出港管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的航班进出港管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

力扣---删除链表的倒数第 N 个结点

给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#xff1a…

解决Word文档中插入MathTypeca公式编号问题(适用于本科、硕士、博士论文编写)

公式编号 这写论文过程中&#xff0c;我们常用到的就是根据章节号要求每写一个公式就自动编号&#xff0c;而不是(1)、&#xff08;2&#xff09;之类的。那么如下图这样的是怎么实现的呢&#xff1f; 1.开启Mathtype右编号 这样你才能有一个编号的格式 2.对公式进行格式化…

C++入门(以c为基础)——学习笔记2

1.引用 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空 间。在语法层面&#xff0c;我们认为它和它引用的变量共用同一块内存空间。 可以取多个别名&#xff0c;也可以给别名取别名。 b/c/d本质都是别名&#…

C++的 stack和queue 的应用和实现【双端队列的理解和应用】

文章目录 stack的理解和应用栈的理解栈的模拟实现string实现stackvector实现stack queue的理解和应用队列的理解队列的模拟实现 双端队列原理的简单理解deque的缺陷为什么选择deque作为stack和queue的底层默认容器STL标准库中对于stack和queue的模拟实现stack的模拟实现queue的…

CSRF介绍及Python实现

CSRF 文章目录 CSRF1. CSRF是什么&#xff1f;2. CSRF可以做什么&#xff1f;3. CSRF漏洞现状4. CSRF的原理5. 举例说明6. CSRF的防御Python示例 1. CSRF是什么&#xff1f; CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;中文名称&#xff1a;跨站请求…

来get属于你的达坦科技令人心动的offer吧!

我们是谁 达坦科技始终致力于打造高性能Al Cloud 基础设施平台DatenLord&#xff0c;积极推动AI应用的落地。DatenLord通过软硬件深度融合的方式&#xff0c;提供高性能存储和高性能网络。为AI 应用提供弹性、便利、经济的基础设施服务&#xff0c;以此满足不同行业客户对AICl…

网络规划(homework 静态路由 and Rip路由表更新)

1、写出下图路由器1和路由器3中的路由表&#xff08;按直接交付、特定主机交付、特定网络交付、 默认交付的顺序放置路由项&#xff09; 2、写出Ri更新后的路由表&#xff08;rip路由协议&#xff09; 1、将Rj广播的路由消息全部1 2、直接对照着更新Ri中的路由表

SQLite字节码引擎(十二)

返回&#xff1a;SQLite—系列文章目录 上一篇&#xff1a;SQLite的架构&#xff08;十一&#xff09;&#xff08;&#xff09; 下一篇&#xff1a;SQLite—系列文章目录 1、 摘要 SQLite 的工作原理是将 SQL 语句转换为字节码和 然后在虚拟机中运行该字节码。本文档 …

车载电子电器架构 —— 工程EOL诊断

车载电子电器架构 —— 工程EOL诊断 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己…

Navicat工具使用

Navicat的本质&#xff1a; 在创立连接时提前拥有了数据库用户名和密码 双击数据库时&#xff0c;相当于建立了一个链接关系 点击运行时&#xff0c;远程执行命令&#xff0c;就像在xshell上操作Linux服务器一样&#xff0c;将图像化操作转换成SQL语句去后台执行 一、打开Navi…

CCF-CSP19<2020-06>-第1/2题

本次难度&#xff1a; 202006-1 线性分类器 题目&#xff1a;202006-1 题目分析&#xff1a; 给定n个点&#xff0c;并标记为AB两类&#xff0c;问给定直线是否能将其分为两个点集。 简单数学知识&#xff0c;点在直线上满足axbyc0&#xff0c;点在直线割平面所得的上下其…

云备份day02

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C云备份项目 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 主要内容介绍了第三方库jsoncpp和bundle库的使用 文章目录 云备…

android 使用ollvm混淆so

使用到的工具 ndk 21.4.7075529&#xff08;android studio上下载的&#xff09;cmake 3.10.2.4988404&#xff08;android studio上下载的&#xff09;llvm-9.0.1llvm-mingw-20230130-msvcrt-x86_64.zipPython 3.11.5 环境配置 添加cmake mingw环境变量如下图: 编译 下载…

Codeforces Round 836 (Div. 2) D. Range = √Sum

题目 思路&#xff1a; #include <bits/stdc.h> using namespace std; #define int long long #define pb push_back #define fi first #define se second #define lson p << 1 #define rson p << 1 | 1 const int maxn 1e6 5, inf 1e18, maxm 4e4 5; c…

PyQt qrc2py 使用PowerShell将qrc文件转为py文件并且将导入模块PyQt或PySide转换为qtpy模块开箱即用

前言 由于需要使用不同的qt环境&#xff08;PySide&#xff0c;PyQt&#xff09;所以写了这个脚本&#xff0c;使用找到的随便一个rcc命令去转换qrc文件&#xff0c;然后将导入模块换成qtpy这个通用库(支持pyside2-6&#xff0c;pyqt5-6)&#xff0c;老版本的是Qt.py(支持pysi…

【力扣每日一题】1026. 节点与其祖先之间的最大差值

LC 1026. 节点与其祖先之间的最大差值 题目描述 给定二叉树的根节点 root&#xff0c;找出存在于 不同 节点 A 和 B 之间的最大值 V&#xff0c;其中 V |A.val - B.val|&#xff0c;且 A 是 B 的祖先。 &#xff08;如果 A 的任何子节点之一为 B&#xff0c;或者 A 的任何子…

算法刷题Day23 | 回溯算法基础理论、 77. 组合

目录 0 引言1 回溯算法基础理论1.1 回溯算法模板1.2 2 组合2.1 我的解题2.2 剪枝操作 &#x1f64b;‍♂️ 作者&#xff1a;海码007&#x1f4dc; 专栏&#xff1a;算法专栏&#x1f4a5; 标题&#xff1a;算法刷题Day23 | 回溯算法基础理论、 77. 组合❣️ 寄语&#xff1a;书…

贪心算法|455.分发饼干

力扣题目链接 class Solution { public:int findContentChildren(vector<int>& g, vector<int>& s) {sort(g.begin(), g.end());sort(s.begin(), s.end());int index s.size() - 1; // 饼干数组的下标int result 0;for (int i g.size() - 1; i > 0;…