fork创建父子进程后子进程终止,父进程无法继续执行如何解决?
问题诊断
- 目标进程ID错误:
fork()调用后,子进程内拿到的pid变量值为0,此时kill(pid, SIGUSR1)的语义是向当前进程组的所有进程发送信号,而非你预期的父进程。子进程要获取父进程ID需要调用getppid()接口。 - 父进程执行速度过快:你当前父进程每次循环仅休眠70微秒,跑完0到1000的循环仅需约70毫秒,远小于子进程先休眠的5秒。等子进程准备发送信号时,父进程已经执行完毕退出,自然无法响应信号,也不会继续执行。
- 可选隐患:
printf、sleep都不是异步信号安全的函数,严格来说不建议在信号处理函数中调用;另外signal注册的信号处理函数默认会中断正在运行的慢系统调用且不会自动重启,可能打断父进程的休眠逻辑。
修复方案
对应修改点如下:
- 子进程发送信号时,用
getppid()获取父进程ID作为kill的第一个参数 - 将父进程的
usleep(70)改为usleep(70000),将每次循环休眠时间调整为70毫秒,总循环耗时约70秒,确保子进程发信号时父进程仍在运行 - 父进程循环结束后调用
wait()回收子进程资源,避免出现僵尸进程
修复后完整代码
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h> static void sigusr(int iSig) { if (iSig == SIGUSR1) { // 演示用,实际生产环境不建议在信号处理函数中调用printf、sleep printf("Received SIGUSR1 signal, going to sleep for 2 seconds\n"); sleep(2); } } int main () { int pid; signal(SIGUSR1, sigusr); pid = fork(); if (pid > 0) { for(int i=0; i<=1000;i++) { printf("%d\n",i); usleep(70000); // 每次休眠70毫秒 } wait(NULL); // 回收子进程 } else { sleep(5); kill(getppid(), SIGUSR1); // 向父进程发信号 exit(0); } }
内容的提问来源于stack exchange,提问作者Mahesh Divate
相关产品推荐
相关产品推荐

