Linux 进程间通信---信号
一、信号基本概念
1.是什么?
(1)比如红绿灯,进程就像车流,当这个车道的红灯亮起来,这个车道的车流就被停下来,(这个时候,在车里的你,可以看下手机或者抽根烟),红绿灯属于这个交通系统,当某个人横穿马路时,这个车道的车流也停了下来,属于外部信号。
(2)当一个车道里有救护车响着警笛穿过来,这时候其他车道停下来,等带救护车通过,相当于,一个进程发送一个信号给另外一个进程。
(3)一个信号的产生叫生成,接收到一个信号的行为叫捕捉;
2.信号的生命周期
(1)信号的三个阶段:①产生信号;②发送信号给进程;③信号的处理和注销;
(2)信号处理的过程;
1)触发信号(可以是系统内部:定时器、硬件异常、也可能是系统外部)
2)注册操作,进入用户空间,找到目标进程的pid将信号值加入到该进程的未处理的信号集合中;
3)信号注销 ,在信号集合中的信号,是进程将要处理的,当CPU处理完其他事情,处理该信号时,先从未处理信号集合中注销该信号,然后立即执行信号处理函数;
3. 信号处理机制
(1)忽略信号 函数信号处理函数指针宏:SIG_IGN
typedef void (*sighandler_t) (int);
sighandler_t signal(int signum,sighandler_t handler);
//功能:注册信号处理函数
//返回值:成功返回信号原来处理方式对应的函数指针值,失败返函数指针:SIG_EER;
//参数:
//signum 捕捉的信号名称
//handler 信号处理函数
(2)默认操作,没有什么影响,默认怎么执行就怎么执行。 SIG_DFL
if(signal(SIGINT,SIG_DFL)==SIG_EER)
{
perror("Fail to signal");
return ;
};
(3)捕捉信号
定义并注册信号处理函数,当信号发生时,执行相应的处理函数。
if(siganl(SIGINT,func)==SIG_ERR)//func 信号处理函数的函数名
{
perror("Fail to signal");
return -1;
}
示例:子进程结束会给父进程发送 SIGCHLD信号,父进程收到这个信号,则调用waitpid(-1,NULL,WNOHANG)回收子进程。
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
void func(int signal)
{
waitpid(-1,NULL,WNOHANG);
printf("child\n");
}
int main(int argc, const char *argv[])
{
pid_t pid;
if(signal(SIGCHLD,func)==SIG_ERR)
{
perror("Fail to signal");
return -1;
}
pid=fork();
if(pid<0)
{
perror("Fail to pid");
return -1;
}
else if(pid==0)
{
sleep(5);
exit(EXIT_SUCCESS);
}
else
{
while(1)
{
printf("father process is running...\n");
sleep(1);
}
}
return 0;
}
4.信号发送函数
(1)int kill(pid_t pid,int sigum);//给指定pid 发送信号
int kill(pid_t pid,int sigum);
//功能:给指定pid 发送信号
//返回值:成功返回0 失败返回-1
//参数:
//pid 进程pid
//sigum 信号
(2)int raise(int signum);//给自己发信号
int raise(int signum);
//功能:给自己发送信号
//返回值:成功返回0 失败返回-1
//参数:
//signum 信号
(3)int alarm(unsigned int seconds);//经过seconds 秒把SIGALRM信号发送给当前进程。
在SIGALRM信号处理函数中再写入alarm()函数,可实现套娃,每隔seconds 秒发送SIGALRM信号。
unsigned int alarm(unsigned int seconds);
//返回值:成功返回0 失败返回-1
//参数:
//seconds 秒