为什么在子进程中有死循环(如下图),而程序运行之后子进程中的死循环自动结束了,并且没有对收到的信号做自定义处理(输出:接收到信号2)呢?
源代码:
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
void accept_signal(int sig){
printf("捕获了信号%d\n",sig);
return;
}
int main(void)
{
pid_t pid = fork();
if(pid < 0){
perror("fork");
exit(EXIT_FAILURE);
}
else if(pid == 0){
signal(SIGINT,accept_signal);
while(1);
}
printf("父进程给子进程%d发送信号2\n",pid);
kill(pid,SIGINT);
return 0;
}
已经解决:在父进程执行kill之前sleep(1);以确保子进程先运行,否则父进程先运行,信号发送是有问题的。
你在程序中不是已经把子进程kill掉了吗?
kill(pid,SIGINT)
把这句注释掉
命令行里输kill -2
另外问问题时,最好附上源码
父进程只是给子进程发送了一个信号2(SIGINT),而子进程对于信号2的处理,并不会按照默认的方式进行(默认是结束进程,子进程死循环被终止),应该按照我们自定义的信号处理函数进行处理(输出:捕获了信号2)。
代码有问题。改成这样:
if(pid < 0){
perror("fork");
exit(EXIT_FAILURE);
}
else if(pid == 0){
signal(SIGINT,accept_signal);
while(1);
}else if(pid > 0)
{
printf("父进程给子进程%d发送信号2\n",pid);
kill(pid,SIGINT);
}
return 0;
一共有两个问题:
第一个问题,如【征途开始的】的描述。fork() 之后的代码,父子进程共享,那就会造成两次信号发送:一次是父进程给子进程发送,一次是自己子进程给自己发送。这大概率不是楼主原本的意图。
第二个问题,子进程的 signal() 对 SIGINT 的配置,可能在父进程的 kill() 调用之后发生。
解决方案:
解决第一个问题,按 【征途开始的】的回复,用 pid 区分父子进程代码逻辑。
解决第二个问题,让父进程在 kill() 调用之前睡眠一会儿,让子进程完成自己的 signal() 调用。另外一种方案是在 fork() 调动之前,调用 signal() 对 SIGINT 进程配置,因为子进程会继承父进程的 sighand ,所以相当于同时配置了父子进程。解决第二个问题的具体代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
volatile int stop = 0;
void signal_handler(int sig)
{
printf("%d(): signal catch: %d\n", getpid(), sig);
}
int main(void)
{
pid_t pid/* = fork()*/;
int ret;
printf("parent is %d()\n", getpid());
// 解决第二个问题的方案2:
// 让子进程会继承父进程的 sighand,这样父进程无需 sleep()
signal(SIGINT, signal_handler);
pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) { // 子进程代码
// 子进程收不到 SIGINT 的原因是,是父进程发送信号的时候,子进程的 SIGINT 尚未配置。
// 在这里配置子进程的 SIGINT 可能来不及:父进程发信号时,子进程的 signal() 调用可能没有完成好。
//signal(SIGINT, signal_handler); // 解决第二个问题的方案1代码片段
while (1)
;
} else { // 父进程代码
printf("parent: send SIGINT to children %d\n", pid);
//sleep(5); // 解决第二个问题的方案1代码片段
kill(pid, SIGINT);
}
return 0;
}