You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用fork实现进程并发?让子进程在父进程退出后运行

实现子进程在父进程退出后执行操作的方法

首先得提一句,你代码里的变量名有点容易混淆——pid_t parent = fork();这里,fork返回0的时候是子进程,返回非0值是父进程拿到的子进程PID,把变量名改成pid_t child_pid = fork();会更清晰,避免后续理解出错。

回到你的问题:确实有办法让子进程等父进程退出后再执行打印,下面给你两种实用的方案:

方案一:用waitpid主动等待父进程退出

子进程可以通过getppid()获取父进程的PID,然后调用waitpid()等待父进程终止。需要注意处理父进程已经提前退出的情况(这时候getppid()会返回1,也就是init/systemd进程的PID),代码示例如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>

int main(int argc, char **argv) {
 FILE *file;
 file = fopen(argv[1], "r");
 if (!file) { // 别忘了加文件打开失败的判断
     perror("fopen failed");
     exit(1);
 }
 char buf[600];
 pid_t first_child = fork();
 if(first_child == 0) {
 while (fgets(buf, sizeof(buf), file)) {
 pid_t grand_child = fork();
 if(grand_child == 0) {
     // 等待父进程(first_child)退出
     pid_t parent_pid = getppid();
     int status;
     // 循环处理waitpid可能的错误
     while (waitpid(parent_pid, &status, 0) == -1) {
         if (errno == ECHILD) {
             // 父进程已经退出,直接执行后续逻辑
             break;
         }
     }
     printf("%s\n", buf);
     fclose(file); // 子进程也要关闭文件句柄
     return(0);
 }
 }
 fclose(file);
 return(0);
 }
 wait(NULL);
 return(0);
}

这种方法的优势是兼容性好,几乎所有类Unix系统都支持,缺点是需要处理错误情况,代码稍显繁琐。

方案二:用prctl让父进程退出时通知子进程

如果是在Linux系统下,可以用prctl()系统调用设置一个“父进程退出信号”——当父进程终止时,内核会给子进程发送指定的信号,子进程等待这个信号后再执行打印。代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <signal.h>

int main(int argc, char **argv) {
 FILE *file;
 file = fopen(argv[1], "r");
 if (!file) {
     perror("fopen failed");
     exit(1);
 }
 char buf[600];
 pid_t first_child = fork();
 if(first_child == 0) {
 while (fgets(buf, sizeof(buf), file)) {
 pid_t grand_child = fork();
 if(grand_child == 0) {
     // 设置父进程退出时发送SIGUSR1信号
     prctl(PR_SET_PDEATHSIG, SIGUSR1);
     // 暂停等待信号
     pause();
     printf("%s\n", buf);
     fclose(file);
     return(0);
 }
 }
 fclose(file);
 return(0);
 }
 wait(NULL);
 return(0);
}

这种方式代码更简洁,但要注意prctl()是Linux特有的接口,在BSD、macOS等系统上无法使用。

另外补充一点:你原代码里主进程只wait(NULL)了一次,也就是只等待第一个子进程退出,但第一个子进程fork出来的那些孙进程会变成孤儿进程,被init/systemd收养。如果需要等待所有子进程退出,你可能需要在第一个子进程里循环调用wait()或者waitpid()。

内容的提问来源于stack exchange,提问作者user9314692

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:34:36