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

父进程创建子进程重复输出:如何在不终止子进程的情况下解决?

问题分析与修复

你的推测其实不太准确,重复输出的核心问题是子进程没有正确退出,导致它会继续执行父进程的代码逻辑,重新进入主循环处理输入(甚至读取到缓冲区的脏数据),进而重复创建 locker。

具体问题点

  • 子进程在完成 locker 创建和管道通信后,没有调用exit()或return终止进程。这意味着子进程会继续执行后续代码——也就是回到父进程的while(1)循环,开始读取用户输入,重复执行CREATE逻辑,导致大量重复输出。
  • 父进程和子进程同时监听标准输入,会出现输入抢占的情况,进一步加剧输出混乱。

修复方案

只需要在子进程的代码块末尾添加退出语句,确保子进程完成任务后立即终止,不会继续执行父进程的循环逻辑。同时可以简化waitpid的使用(你当前的while循环是多余的,单个子进程用一次waitpid就足够)。

修改后的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include "locker.h"
#include <signal.h>
#include <stdarg.h>

#define P1_READ 0
#define P2_WRITE 1
#define P2_READ 2
#define P1_WRITE 3
#define NUM_PIPES 2

pid_t this_pid;

int main(){
    char buffer[100];
    int locker_count = 0;
    int fd[2*NUM_PIPES];
    int len = 0, i;
    pid_t pid_list[100], wpid;
    memset(pid_list,0,100);
    pid_t this_pid;
    struct locker_t new_locker = { .id = 0, .user_id = 0, .locked = 1, .owned = 0};
    fflush(stdout);
    while(1){
        scanf("%s", buffer);
        fflush(stdout);
        if(strcmp(buffer, "CREATE") == 0){
            for(i = 0; i < NUM_PIPES; ++i){
                if(pipe(fd+(i*2)) < 0){
                    perror("Failed to allocate pipes");
                    exit(EXIT_FAILURE);
                }
            }
            fflush(stdout);
            this_pid = fork();
            if(this_pid == 0){
                //close descriptors we don't need in this process
                close(fd[P1_READ]);
                close(fd[P1_WRITE]);
                len = read(fd[P2_READ], &locker_count, sizeof(locker_count));
                //increase by 1
                locker_count++;
                //create locker
                new_locker.id = locker_count;
                printf("New Locker Created: %d\n", locker_count);
                printf("\n");
                write(fd[P2_WRITE], &locker_count, sizeof(locker_count));
                //finished. close remaning descriptors
                close(fd[P2_READ]);
                close(fd[P2_WRITE]);
                // 关键修复:子进程执行完后立即退出
                exit(EXIT_SUCCESS);
            }
            if(this_pid > 0){
                //close unneeded descriptors
                close(fd[P2_READ]);
                close(fd[P2_WRITE]);
                write(fd[P1_WRITE], &locker_count, sizeof(locker_count));
                //now wait for response
                len = read(fd[P1_READ], &locker_count, sizeof(locker_count));
                //pid_list[(locker_count-1)] = this_pid;
                close(fd[P1_READ]);
                close(fd[P1_WRITE]);
                fflush(stdout);
                // 简化waitpid:单个子进程只需等待一次
                waitpid(this_pid, NULL, 0);
            }
        }
        if(strcmp(buffer, "QUIT") == 0){
            exit(0);
        }
    }
}

额外说明

  • 子进程退出后,父进程通过waitpid回收其资源,避免僵尸进程。
  • 现在每次执行CREATE命令时,只会创建一个子进程,完成任务后立即退出,不会再出现重复输出的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:59:22