目录
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.观察现象
结论:
- 信号的阻塞是不会干扰信号注册的
- 可靠信号在收到多次,会处理多次。而非可靠信号接收多次,只处理一次。非可靠信号有可能会导致信号丢失。
- 先处理可靠信号(实时信号)(按序号处理34-64),再处理非可靠信号(非实时信号)
- 9号信号和19号信号是不能被阻塞的
判断ctrl+z是19号信号(SIGSTOP)还是20号信号(SIGTSTP)
9. volatile关键字
保持内存可见性
volatile修饰一个变量,变量在执行代码时不允许从寄存器当中获取值,必须从内存当中获取