| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 系统运维 -> Linux_进程信号(进程信号生命周期_Core Dump调试_进程信号捕捉_系统调用向进程发送信号_阻塞信号_信号集函数_处理信号内核态与用户态_C语言volatile关键字_SIGCHLD信号) -> 正文阅读 |
|
[系统运维]Linux_进程信号(进程信号生命周期_Core Dump调试_进程信号捕捉_系统调用向进程发送信号_阻塞信号_信号集函数_处理信号内核态与用户态_C语言volatile关键字_SIGCHLD信号) |
文章目录
1.进程信号的生命周期1.在进程收到信号前,进程内部可以识别信号,并且对应信号做出相应的措施。进程信号属于进程内部的特有属性。
2.信号的种类与记录信号的种类如上图白色背景的是普通信号,黑色背景的是实时信号 信号本质是系统提供的宏值,宏的名称为后面的英文,宏的值为前面的数值。 普通信号的记录(位图)信号记录在进程的(task_struct)PCB中,以位图这种数据结构来记录普通信号是否产生。 普通信号的范围是1到31
3.信号产生命令发送信号(kill -信号编号/信号名称 -进程pid)eg:向进程发送2号信号 键盘按键向前台进程发送信号eg:ctrl+c向前台进程进程发送2号信号 4.Core Dump核心转储
开启核心转储(ulimit -c)ulimit -a查看core file size的大小,如果大小为0表示关闭核心转储 Core Dump调试(gdb下core-file+core文件名)
退出码:(status>>8)&0xff eg:以除零错误举例子 *为什么C/C++程序会崩溃当发生除零,野指针,越界错误时,程序崩溃,本质是由操作系统向对应错误进程发送信号导致的。 cpu中存在状态寄存器.当发生除零错误时,状态寄存器中的溢出标志位会从0变为1。 同理:例如野指针和越界问题是因为进程地址空间在MMU(硬件单元+页表)映射到物理内存时,操作系统识别到MMU的状态信息中不存在对应的映射关系,向对应页表的进程发送信号使程序崩溃。 这些错误一定在硬件上会有所表现,操作系统识别到硬件错误使得进程崩溃。 5.信号捕捉(signal函数signal.h)
6.向指定的进程发送指定的信号(kill函数signal.h+sys/types.h)eg:模拟kill命令 kill命令的结构为:kill+进程pid+信号编号 所以要向main函数传入命令行参数 argv[0]代表程序名称,argv[1]代表进程pid,argv[2]代表信号编号
进程自己向自己发送信号(raise函数signal.h)
进程自己向自己发送6号信号(abort函数stdlib.h)
由软件条件产生信号(alarm函数unistd.h)在进程与进程用管道通信时,当读取端关闭后,写入端会立即被操作系统终止。本质是操作系统向进程发送13号信号SIGPIPE,当前写入条件不允许这种信号称为由软件条件产生的信号
eg:
7.阻塞信号
深入理解信号在进程PCB中的存储(block,pending位图,handler函数指针数组)当进程收到信号后,先将pending位图的对应位置改为1,在看block位图对应比特位值是否为1.如果对应的信号没有被阻塞,则开始递达在handler数组中找对应的递达方法,否则对应的信号被阻塞。 注意:对于普通信号,如果在这个信号被阻塞的过程中,信号产生多次,在Linux中只记录一次这个信号;对于实时信号而言,在递达前如果产生多次,这些信号被依次放入队列中。 信号集操作函数修改block,获取pending位图(sigset_t)信号集操作函数都在signal.h的头文件下,其调用成功返回0失败返回-1。特殊的是sigismember函数其返回值是一个bool值,用来判断一个信号集中是否包括某种信号,返回1代表包括,0代表不包括,-1代表调用失败 sigset_t变量定义在用户区的一个变量,它的修改不会影响进程,我们要通过系统调用将这个设置好的变量传入到操作系统中,让操作系统修改进程的pcb达到修改位图的目的 sigemptyset函数(初始化sigset_t变量)
sigaddset函数(将信号添加到sigset_t变量中)sigdelset函数(将信号从sigset_t中删除)sigfillset函数(将sigset_t位图中所有比特位置1)函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系统支持的所有信号。 sigismember函数(判断一个信号集的有效信号中是否包含某种信号)
sigprocmask函数(读取或更改进程的信号屏蔽字(阻塞信号集)修改block位图)
how参数可选值
返回值:成功为0,失败-1; sigpending函数(获取进程的pending位图)
demo_打印进程的pending位图
运行结果为: 如上图,阻塞了2号信号后向进程发送2号信号pending位图2号位置值变为1,代表收到了这个信号;之后取消了对2号信号的阻塞,2号信号递达后被捕捉执行自定义行为,pending位图中对应位置的值从1到0。 8.处理信号进程在收到信号后在递达要处理信号时不是立即处理,而是在内核态切换到用户态时进行信号的处理 内核态与用户态用户态:执行用户自己的代码时系统的状态称为用户态。 内核态:执行系统调用的代码,本质是调用内核的代码,必须要内核级别的权限 每一个进程不仅拥有用户级页表,还有一张内核页表,用来映射内存中的操作系统代码和进程的进程地址空间,实现进程切换等操作。 只有在内核态才可以访问内核空间,内核态通常用来执行操作系统的代码状态,权限较高。 内核态与用户态切换cpu上存在寄存器可以标识当前处于用户态还是内核态。 同时cpu上也存在寄存器保存页表,状态切换本质上是切换cpu上的用户页表和内核页表。 切换过程如下图 需要注意的是: 大体切换流程如下图 sigaction函数(与signal函数相似实现信号捕捉_读取和修改与指定信号相关联的处理动作)参数解释: 返回值:
9.C语言volatile关键字(保持内存的可见性)分析下面的代码:
当接受到2号信号时,flag变为1,while循环条件不满足,此时会打印End
所以给flag变量加上volatile关键字,每次在检测这个变量的值时,先从内存中读取,再放到寄存器中,保证内存的可见性 10.SIGCHLD信号(通过信号的方式回收子进程)为了避免僵尸进程的出现,子进程在退出时必须由父进程等待。
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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/16 2:50:19- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |