ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Linux下的信号详解

2020-11-29 17:02:33  阅读:116  来源: 互联网

标签:sigqueue 处理 阻塞 int 详解 信号 Linux 进程


信号

1.信号是什么

通知进程发生了某个事件,打断进程当前操作,去处理这个事件。是一个软件中断,功能是事件通知。

例如:

输入命令,在Shell下启动一个前台进程。 用户按下Ctrl-C,键盘输入产生一个硬件中断。
如果CPU当前正在执行这个进程的代码,则该进程的用户空间代码暂停执行, CPU从用户 态切换到内核态处理硬件中断。
终端驱动程序将Ctrl-C解释成一个SIGINT信号,记在该进程的PCB中(也可以说发送了一 个SIGINT信号给该进程)。
当某个时刻要从内核返回到该进程的用户空间代码继续执行之前,首先处理PCB中记录的信号,发现有一个SIGINT信号待处理,而这个信号的默认处理动作是终止进程,所以直接 终止进程而不再返回它的用户空间代码执行。

2.信号的种类

kill -l 查看信号
非可靠信号:1~31号信号,信号可能会丢失
可靠信号:34~64号信号,信号不可能丢失
在这里插入图片描述
SIGHUP:1号信号,Hangup detected on controlling terminal or death of controlling process(在控制终端上挂起信号,或让进程结束),ation:term

SIGINT:2号信号,Interrupt from keyboard(键盘输入中断,ctrl + c ),action:term

SIGQUIT:3号信号,Quit from keyboard(键盘输入退出,ctrl+ | ),action:core,产生core dump文件

SIGABRT:6号信号,Abort signal from abort(3)(非正常终止,double free),action:core

SIGKILL:9号信号,Kill signal(杀死进程信号),action:term,该信号不能被阻塞、忽略、自定义处理

SIGSEGV:11号信号,Invalid memory reference(无效的内存引用,解引用空指针、内存越界访问),action:core

SIGPIPE:13号信号,Broken pipe: write to pipe with no readers(管道中止: 写入无人读取的管道,会导致管道破裂),action:term

SIGCHLD:17号信号,Child stopped or terminated(子进程发送给父进程的信号,但该信号为忽略处理的)

SIGSTOP:19号信号,Stop process(停止进程),action:stop

SIGTSTP:20号信号,Stop typed at terminal(终端上发出的停止信号,ctrl + z),action:stop

具体的信号采取的动作和详细信息可查看:man 7 signal

3.信号的产生

硬件产生即通过终端按键产生的信号:

ctrl + c:SIGINT(2),发送给前台进程,& 进程放到后台运行,fg 把刚刚放到后台的进程,再放到前台来运行
ctrl + z:SIGTSTP(20),一般不用,除非有特定场景
ctrl + | :SIGQUIT(3),

软件产生
软件产生即调用系统函数向进程发信号
kill命令 :例如: kill -9 pid

系统调用
int kill(pid_t pid,int signum) 给pid进程发送指定信号
int raise(int signum) 给自身发送信号
void abort() 给自身发送异常信号,6号信号
int alarm(int sec) sec秒以后给自身发送SIGALRM信号(定时器)

4.信号的注册

信号注册又分为可靠信号的注册和非可靠信号的注册。

在进程pcb中有个表(位图),–> 未决信号集合(没有被处理的),进程运行中通过这张表可以知道自己收到了什么信号。
信号注册其实就是修改这个位图,将对应的信号位 置为1.
但是,位图只能知道自己收到了这个信号,但是不知道收到了多少个此信号
因此,在pcb中还有一个sigqueue 双向链表,来一个信号,开辟一个节点,

非可靠信号的注册

当进程收到非可靠信号时:
将非可靠信号对应的比特位置为1
添加sigqueue节点到sigqueue队列当中,但是,在添加sigqueue节点的时候,队列当中已然有了该信号的sigqueue节点,则不添加

可靠信号的注册

当进程所受到可靠信号时:
在sig位图中更改信号对应的比特位为1
不论之前sigqueue队列中是否存在该信号的sigqueue节点,都再次添加sigqueue节点到sigqueue队列当中去

5.信号的注销

非可靠信号的注销
信号对应的比特位从1置为0
将该信号的sigqueue节点从sigqueue队列当中进行出队操作

可靠信号的注销
将该信号的sigqueue节点从sigqueue队列当中进行出队操作
需要判断sigqueue队列当中是否还有相同的sigqueue节点:
①没有了:信号比特位从1置为0
②还有:不会更改sig位图中的比特位

在这里插入图片描述

6.信号阻塞

在这里插入图片描述

信号的阻塞,并不会干扰信号的注册。信号能注册,但不能被立即处理, 将block位图中对应的信号比特位置为1,表示阻塞该信号

进程收到该信号,还是一如既往的注册 当进程进入到内核空间,准备返回用户空间的时候,调用do_signal函数,就不会立即去处理该信号了

当该信号不被阻塞后,就可以进行处理了

函数原型:

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

参数解释:

how,该做什么样的操作 SIG_BLOCK:设置信号为阻塞 SIG_UNBLOCK:解除信号阻塞 SIG_SETMASK:替换阻塞位图
set:用来设置阻塞位图 SIG_BLOCK:设置某个信号为阻塞,block(new) = block(old) | set
SIG_UNBLOCK:解除某个信号阻塞,block(new)= block(old) & (~set)
SIG_SETMASK:替换阻塞位图,block(new)= set oldset:原来的阻塞位图

返回值:成功返回0,失败返回-1.

其他配套使用的函数:
在这里插入图片描述

7.信号的处理方式

默认处理方式: (系统中既定义好的-没有特殊指定时采用的处理方式)

忽略处理方式:什么都不做,信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。

自定义处理方式:

signal函数
该函数可以更改信号的处理动作。

typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
参数解释:

signum:更改的信号值
handler:函数指针,要更改的动作是什么
SIG_IGN :忽略处理;SIG_DFL默认处理

实际上,该函数内部也调用了sigaction函数。

sigaction函数
读取和修改与指定信号相关联的处理动作。

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
参数解释:

signum:待更改的信号值

void     (*sa_handler)(int);//函数指针,保存了内核对信号的处理方式
void     (*sa_sigaction)(int, siginfo_t *, void *);//
sigset_t   sa_mask;//保存的是当进程在处理信号的时候,收到的信号
int        sa_flags;//SA_SIGINFO,OS在处理信号的时候,调用的就是sa_sigaction函数指针当中
//保存的值0,在处理信号的时候,调用sa_handler保存的函数
void     (*sa_restorer)(void);

在这里插入图片描述
信号处理流程图
在这里插入图片描述

task_struct结构体中有一个struct sighand_struct结构体。
struct sighand_struct结构体有一个struct k_sigaction action[_NSIG]结构体数组。
该数组中,其中的_sighandler_t sa_handler保存的是信号的处理方式,通过改变其指向,可以实现我们对自定义信号的处理

程序运行如何从用户态切换到内核态:系统调用、异常、中断

用户态:程序运行的是用户自己写的函数或者库函数
内核态: 运行的是内核中的代码完成内核的某个功能

信号的处理是在内核态返回用户态之前进行的。调用 do_sigal() 接口。

对于默认处理和忽略处理,直接在内核态完成;自定义处理 需要进入用户态进行处理,处理完以后返回内核态,查看还有无需要处理的信号,如果没有则返回用户态。

标签:sigqueue,处理,阻塞,int,详解,信号,Linux,进程
来源: https://blog.csdn.net/weixin_51582527/article/details/110318621

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有