父进程创建子进程重复输出:如何在不终止子进程的情况下解决?
问题分析与修复
你的推测其实不太准确,重复输出的核心问题是子进程没有正确退出,导致它会继续执行父进程的代码逻辑,重新进入主循环处理输入(甚至读取到缓冲区的脏数据),进而重复创建 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
相关产品推荐
相关产品推荐

