核心词汇:信号、signal
信号:系统预先定义好的特定事件,信号可以被产生,也可以被接收,产生和接收信号的主体是进程。
signal函数:修改信号的相应方式。
一、signal函数格式
typedef void (*Fun) (int);
Fun signal(int signum, Fun fun);
- 参数一:int signum
signum代表信号类型,类型是整型int。
举例:SIGINT(结束当前进程)、SIGCHLD(子函数结束给父函数的信号)
这些信号在linux系统下,存放的路径是/usr/include/bits/signum.h,他们都是一些宏。 - 参数二:Fun fun
fun代表相应方式,类型是函数指针void *(int)
三种:默认SIG_DEF、忽略SIG_IGN、自定义void fun(int sign); - 返回类型:Fun
返回的类型也是函数指针void *(int)
二、例一
signal(SIGINT,fun)
将信号SIGINT的相应类型由默认改为自定义。
- 当有信号进入进程的时候,进程会中断,信号按照默认的方式执行,等信号(f非常快)执行完进程再继续执行。
- 如果我们用signal在程序中对相应方式做出了修改,那么他就会按照新的相应方式处理。
- 但需要注意的是如果把signal写到了程序末尾,那信号进来的时候程序可能还没有执行到末尾,这个signal就是失败的,所以我们一般把signal写在程序前面。
- 最后,如果我们写了两个signal,那么第二个就会把第一个覆盖掉。比如signal(SIGCHLD,SIG_IGN);signal(SIGCHLD,SIG_IGN);它的解释就是SIGCHLD的相应方式由默认改为忽略,再由忽略改为自定义,当信号进来的时候直接就以自定义处理。
三、例二
signal(SIGCHLD,SIG_IGN)
将子函数结束给父函数的信号SIGCHLD的相应类型,由默认改为忽略
- 问:父函数本身默认的处理凡是就是忽略,那么这条语句还有作用吗?
- 答案:有,子函数结束后变成僵死进程,默认忽略的处理方式不会处理僵死进程,而给改为忽略的处理方式后,系统init会处理僵死进程。
- 原因:关键在于系统知不知道父函数的处理方式是忽略?如果系统知道了父函数的处理方式是忽略,表明父函数就不用子函数了,它就会帮助父函数处理掉僵死进程。反之就不会。
默认忽略和更改为忽略虽然都表示忽略这个进程,但默认忽略是父函数的默认处理方式,然而操作系统却不知道,所以更改为忽略,这条语句一执行,系统就知道了父函数的处理方式是忽略,另一方面系统不允许由僵尸进程的出现,就直接处理了它。