【Linux】进程间通信---信号
1.信号
- 信号是一个中断软件
- 信号的种类
1~31:非可靠信号
34~64:可靠信号
2.信号的产生方式
硬件产生
ctrl + c:2号信号,导致前台进程终止
ctrl + z :20号信号(SIGTSTP),导致前台进程暂停
ctrl + |:3号信号(SIGQUIT)
软件产生
kill函数 kill(pid_t pid, int signo)
kill -[信号][pid] —>eg:kill -9 12121
abort(pid_t pid):—>6号信号(SIGABORT)—>(double free)
解引用空指针+内存访问越界— >进程收到11号信号(SIGSEGV)
3.信号的注册
- 在使用sig数组的时候不是按照数组的方式去使用的,而是按照比特位的方式去使用的
-
对于sig位图当中的bit位,每一个比特位有与之对应的信号,直到将我们当前操作系统的信号表示完毕
3.信号的注册
-
当进程收到一个非可靠信号
-
第一件事情:将非可靠信号对应的比特位更改为1
-
第二件事情:添加sigqueuej节点到sigqueue队列当中
-
注意:队列当中已经有了该 信号的sigqueue节点,则不添加
-
如果进程收到一个可靠信号
-
第一件事情:在sig位图当中更改该信号对应的比特位为1
-
第二件事情:不论之前sigqueue队列当中是否存在该信号的sigqueue节点,都再次添加sigqueue节点到sigqueue队列当中;
4.信号的注销
- 非可靠信号的注册
- 将该信号的sigqueue节点从sigqueue队列当中的出队操作
- 信号在sig位图当中对应的比特位从1置为0
- 可靠信号的注销
- 将该信号的sigqueue节点从sigqueue队列当中进行出队操作
- 需要判断sigqueue队列当中是否还有相同的sigqueue节点
没有:信号在sig位图当中对应的比特位从1置为0
有:不会更改sig位图当中对应的比特位
5.信号的处理
- SIG_DFL:默认处理方式
- SIG_IGN:忽略处理(SIGCHLD)
-
自定义信号处理方式
signal函数
typedef void (*sighandler_t )(int);
sighanler_t signal(int signum, sighhandler_t handler);
该函数可以更改信号的处理方式
6.sigaction函数
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
- signum:待更改的信号的值
- struct sigaction
struct sigaction{
void (*sa_handler)(int):函数指针,保存内核对信号的处理方式
void (*sa_sigaction)(int, siginfo_t , void)
sigset_t sa_mask:保存的是当前进程在处理信号的时候,收到的信号
int sa_flags:SA_SIGINFO,操作系统在处理信号的时候,调用的就是sa_sigaction函数指针当中保存的值0,在处理信号的时候,调用sa_handler保存的函数
void (*sa_restorer)(void) :预留信息
};
act:将信号处理函数改变act
oldact:信号之前的处理方式
int sigempty(sigset_t *set); // 将位图的所有比特位设置为0
7.信号的捕捉流程
- 什么时候进入到内核空间:调用系统调用函数的时候,或者调用库函数的时候(库函数底层大多数都是封装系统调用函数的)
8.信号的阻塞
-
信号的阻塞并不会干扰信号的注册,只不过当前的进程不能立即处理
- 当我们将block位图当中对应信号的比特位置为1,表示当前今后才能阻塞该信号
- 当进程收到一个该信号的时候,进程还是一如既往的对该信号进行注册
- 当进程进入到内核空间,准备返回用户空间的时候,调用do_signal函数,这会儿不会立即去处理该信号了
- 这里面的不会立即处理,一定不是之后处理
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); -
how:告诉sigprocmask函数,应该进行什么操作
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:原来的阻塞位图