【Linux】8. 进程信号(信号的种类、产生方式、注册、注销、处理方式,信号的捕捉流程、阻塞、volatile关键字)

1. 信号的概念

信号是一个软件中断(就是有一个这样的事情,你要不要处理)。
中断方式除了软件中断,还有一个硬件中断(MMU)

2. 信号的种类

kill -l:查看信号的种类,共62个
在这里插入图片描述

2.1非可靠信号(非实时信号),[1,31]:不可靠,信号有可能会丢失
2.2可靠信号(实时信号,real time),[34,64]:可靠信号,信号绝对不会丢失

3. 信号的产生方式

3.1 硬件产生

(1) ctrl + c:发送的是2号信号 SIGINT,结束前台进程
在这里插入图片描述
(2) ctrl + z:发送的是20号信号 SIGTSTP,暂停进程,进程会转向后台运行
在这里插入图片描述
fg命令:将暂停的进程转到前台进行
在这里插入图片描述
(3) ctrl + |:发送的是3号信号 SIGQUIT,终止进程并产生核心转储文件
没有产生coredump文件的原因:(1)若core file size:0;产生coredump文件的大小为0,就不用产生了。(2)若core file size:unlimited,产生coresump文件的大小是无限制的,但是还没有产生coredump文件的原因就是当前磁盘空间不足。
ulimit -a 命令: 用来显示当前的各种用户进程限制
在这里插入图片描述
怎么看信号的功能:命令:man 7 signal
当前信号的处理方式:
在这里插入图片描述
在这里插入图片描述

3.2 软件产生

3.2.1 kill命令

kill -9命令

3.2.2 kill函数

int kill(pid_t pid,int sig);
在这里插入图片描述
在这里插入图片描述

3.2.3 raise函数

raise函数:int raise(int sig); 谁调用谁接收到信号
在这里插入图片描述
在这里插入图片描述

3.2.4 abort函数

abort函数:发送的是6好信号 SIGABRT
在这里插入图片描述
在这里插入图片描述

3.2.5 alarm函数

alarm函数:发送14号信号 SIGALRM
在这里插入图片描述
在这里插入图片描述

4. 信号的注册

注册是操作系统内核给进程发送了一个信号
sigqueue队列
前提:同一个信号注册两次
非可靠信号的注册:
第一次:将信号对应的比特位改成1+在sigqueue队列中添加sigqueue节点
第二次:只会将信号对应的比特位从1改为1,不会添加sigqueue节点
可靠信号的注册:
第一次:将信号对应的比特位改成1+在sigqueue队列中添加sigqueue节点
第二次:还会在sigqueue队列中添加可靠信号的sigqueue节点

5. 信号的注销

注销是处理内核给进程发送的这个信号
非可靠信号的注销:将信号对应在sig位图当中的比特位置为0,并且将sigqueue节点从sigqueue队列当中进行出队操作
可靠信号的注销:
第一步:将可靠信号对应的sigqueue节点从sigqueue队列当中进行出队操作
第二部:判断sigqueue队列当中是否还有当前可靠信号的sigqueue节点。如果没有:则将sig位图当中可靠信号对应的比特位置为0;如果有:则不会将sig位图当中的可靠信号对应的比特位置为0。

6. 信号的处理方式

6.1 默认的处理方式:SIG_DFL(signal default)

6.2 忽略处理:SIG_IGN(signal ignore)

                       SIGCHLD信号:子进程在退出的时候会给父进程发送一个SIGCHLD信号

6.3 自定义处理:更改信号的处理方式

自定义处理的函数:

6.3.1 signal函数

typedef void(*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signum:待自定义处理函数的信号
handler:接收一个函数地址,该函数的返回值为void,参数为int,参数的含义为当进程收到某个信号触发调用了该函数的时候,会将该信号的值,传递给该函数。
在这里插入图片描述
在这里插入图片描述
按下ctrl+c就会打印输出

6.3.2 sigacion函数

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
signum:待自定义处理函数的信号
act:向要将信号更改成什么处理动作
oldact:信号之前的处理动作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第一次ctrl+c打印内容
第二次ctrl+c退出

7. 信号的捕捉流程

在这里插入图片描述
执行流从内核态切换到用户态之前一定会调用do_signal函数处理信号
从用户态切换到内核态的时候,是调用了系统调用函数,或者进程异常

8. 信号的阻塞

信号的阻塞指的是当准备处理信号的时候,会判断当前信号是否为阻塞,如果该信号为阻塞,则暂时不去处理信号。在这里插入图片描述
例如:sig位图中的第三个比特位为1,则发送2号信号
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
how:告诉sigprocmask函数以什么样的方式进行工作
          SIG_BLOCK:设置某个信号为阻塞状态
                  block(new) = block(old) | set
                         block(old): 0010 1100
                                   set  :  0000 0010
                            按位或 | :  0010 1110
          SIG_UNBLOCK:解除信号为阻塞状态
                  block(new) = block(old) & (~set)
                                   set : 0000 0100
                          取反~set : 1111 1011
                          block(old): 0010 1100
                           按位与 &: 0010 1000
          SIG_SETMASK:替换原来的block位图
          block(new) = set
oldset:在没有更改之前老的block位图

验证可靠信号和非可靠信号
给一个进程阻塞所有的信号,然后发送几次可靠信号和几次非可靠信号,在解除阻塞之后,进程处理了几次可靠信号和非可靠信号

步骤:
1.怎样判断当前进程收到某个信号?
更改信号的处理方式
1.1 非可靠信号:2号信号
1.2可靠信号:40号信号
2.阻塞所有信号
3.给当前进程发送多次2号信号和40号信号
4.解除所有信号的阻塞
5.观察现象
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结论:

  1. 信号的阻塞是不会干扰信号注册的
  2. 可靠信号在收到多次,会处理多次。而非可靠信号接收多次,只处理一次。非可靠信号有可能会导致信号丢失。
  3. 先处理可靠信号(实时信号)(按序号处理34-64),再处理非可靠信号(非实时信号)
  4. 9号信号和19号信号是不能被阻塞的

判断ctrl+z是19号信号(SIGSTOP)还是20号信号(SIGTSTP)
在这里插入图片描述
在这里插入图片描述

9. volatile关键字

保持内存可见性
volatile修饰一个变量,变量在执行代码时不允许从寄存器当中获取值,必须从内存当中获取
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值