| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> Linux信号捕捉 -> 正文阅读 |
|
[系统运维]Linux信号捕捉 |
1.上节回顾上节主要学习了信号发送前,信号发送中。1.信号发送前信号产生的方式:1.键盘 2.进程异常 3.系统调用 4.软件条件 附加:1.信号产生的方式有非常多,但是最终发送都是由OS统一发送2.core dump && waitpid-> core dump flag3.信号发送之后,不是被立即处理的,而是在合适的时候a.进程就需要有保存信号的能力 b.“合适”:是什么时候? 2.信号发送中需要记住一张最重要的图pending:保存信号,已经收到但是还没有被抵达的信号OS发送信号的本质:修改目标进程的pending位图bolck:状态位图,表示那些信号不应该被抵达,直到解除阻塞!block也叫信号屏蔽字hander:函数指针数组,【31】,每个信号的编号就是该数组的下标3.信号发送后?1.sigprocmask
如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则 更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号 屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值
如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递 达。2.信号集操作函数?
sigset_t
类型对于每种信号用一个
bit
表示
“
有效
”
或
“
无效
”
状态
,
至于这个类型内部如何存储这些
bit
则依赖于系统
实现
,
从使用者的角度是不必关心的
,
使用者只能调用以下函数来操作
sigset_ t
变量
,
而不应该对它的内部数据做
任何解释
,
比如用
printf
直接打印
sigset_t
变量是没有意义的
函数
sigemptyset
初始化
set
所指向的信号集
,
使其中所有信号的对应
bit
清零
,
表示该信号集不包含 任何有
效信号。
函数
sigfifillset
初始化
set
所指向的信号集
,
使其中所有信号的对应
bit
置位
,
表示 该信号集的有效信号包括系
统支持的所有信号。
注意
,
在使用
sigset_ t
类型的变量之前
,
一定要调 用
sigemptyset
或
sigfifillset
做初始化
,
使信号集处于确定的
状态。初始化
sigset_t
变量之后就可以在调用
sigaddset
和
sigdelset在该信号集中添加或删除某种有效信号。
这四个函数都是成功返回
0,
出错返回
-1
。
sigismember
是一个布尔函数
,
用于判断一个信号集的有效信号中是否包含
某种 信号
,
若包含则返回
1,
不包含则返回
0,
出错返回
-1
。
3.sigpending
#include <signal.h>
sigpending
读取当前进程的未决信号集
,
通过
set
参数传出。调用成功则返回
0,
出错则返回
-1
。 下面用刚学的几个函数做个实验。
程序如下:
我们屏蔽掉2号信号(相当于在block中2号设置为1),此时我们发送二号信号,就没有任何作用
下面我们屏蔽二号信号,向进程发送二号信号,二号信号被屏蔽所以不会被抵达,我们向进程发送二号信号,知识二号信号一定会保存在pending表中我们打印pending表? ??
可以看出当我们屏蔽掉2号信号,在发送二号信号,则该信号不会被递达会被保存在pending位图中,该位置会被设置为1下面在观察,我们屏蔽二号信号,在打印pending表后,中途我们解除对2号信号的屏蔽,在观察结果
?可以看出当发送二号信号是会被屏蔽,pending位图2号位被设置为1,当打印达到20次时,解除屏蔽,信号会被立即抵达,并会调用我们自己写的信号捕捉方法信号什么时候被处理?因为信号是被保存在进程PCB中 ,pending位图中,处理方式有:a.默认 b.忽略 c.自定义 那到底是什么时候处理信号,前面我们也说过信号的处理是在合适的时候当进程从内核态返回到用户态的时候,进行上面的检查并进行处理工作!那什么是用户态和内核态我们先感性的认识如下图?例如当用户调用open()系统调用的时候,会嵌入到内核,在内核中执行open方法在返回到用户态我们在理性的认识?在CPU中会有一个CR3寄存器CR3寄存器的改变与操作系统的关联主要是由于进程切换,每当进程切换时,CR3的内容需要被操作系统修改。先了解一下进程切换的具体内容,从本质上说,每个进程切换由两部分组成:1、切换页全局目录以安装一个新的地址空间2、切换内核态堆栈和硬件上下文,因为硬件上下文提供了内核执行新进程所需要的所有信息,包括CPU寄存器。总结1.当执行系统调用的时候,我们会从用户态到内核态的转变,CPU中CR3寄存器会设置相应的标志位2.进程切换的时候,操作系统的内核代码通过内核页表,让每个进程看到都是同一份,而用户空间的代码和数据可以多分,相当于内核是一个基础而用户的代码和数据就相当于钩子挂在内核上运行的3.信号处理机制?那什么内核不能直接执行用户空间的代码呢,不是内核态可以看到内核的代码也可以看到用户的代码吗?其实理论上可以实现的,但是如果有人恶意破坏的话,就完了,比如在hander方法中写了(rm rf /)的实现,你又是内核态去执行的,可能会删掉所有的文件和数据,那不是就拉闸了吗如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。 当前正在执行main函数,这时发生中断或异常切换到内核态。 在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。 内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函 数,sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控制流程。 sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行了4.sigaction
? sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,出错则返回- 1。signo是指定信号的编号。若act指针非空,则根据act修改该信号的处理动作。若oact指针非 空,则通过oact传出该信号原来的处理动作。act和oact指向sigaction结构体:将sa_handler赋值为常数SIG_IGN传给sigaction表示忽略信号,赋值为常数SIG_DFL表示执行系统默认动 作,赋值为一个函数指针表示用自定义函数捕捉信号,或者说向内核注册了一个信号处理函 数,该函数返回 值为void,可以带一个int参数,通过参数可以得知当前信号的编号,这样就可以用同一个函数处理多种信 号。显然,这也是一个回调函数,不是被main函数调用,而是被系统所调用。当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止。 如果在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字。 sa_flflags字段包含一些选项,本章的代码都把sa_flflags设为0,sa_sigaction是实时信号的处理函数,本章不详细解释这两个字段,有兴趣的同学可以在了解一下。
? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/15 17:47:16- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |