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

进程通信代码疑问:先回收子进程会导致无法打印吗?如何解决?

问题分析与解决方案

结论

确实存在无法正常打印的情况。

问题原因

当前代码存在两个核心问题:

  1. 父进程持有管道写端未关闭:父进程创建管道后,没有关闭管道的读写描述符。当第二个子进程写入数据退出后,父进程仍持有管道写端,导致第一个子进程的read()调用会一直阻塞(因为管道写端并未完全关闭,不会触发EOF),程序卡住无法打印内容。
  2. 子进程输出缓冲未刷新:第二个子进程中printf("HI")没有换行符,stdout默认是行缓冲模式,数据可能被暂时缓存,无法立即写入管道,进一步加剧阻塞问题。

解决方法

通过三个关键点修复代码:

修复后的代码示例

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

int main() {
    pid_t c[2];
    int p[2];

    // 增加管道创建错误检查
    if (pipe(p) == -1) {
        fprintf(stderr, "pipe error");
        exit(EXIT_FAILURE);
    }

    c[0] = fork();
    if (c[0] < 0) {
        fprintf(stderr, "fork error");
        exit(EXIT_FAILURE);
    } else if (c[0] == 0) {
        // 第一个子进程:读取管道数据
        close(p[1]); // 关闭未使用的写端
        dup2(p[0], STDIN_FILENO); // 安全替换标准输入
        close(p[0]); // 复制后关闭原描述符

        char buf[BUFSIZ];
        ssize_t n = read(STDIN_FILENO, buf, BUFSIZ);
        if (n > 0) {
            buf[n] = '\0'; // 手动添加字符串终止符,避免垃圾字符
            printf("Second child's print: %s\n", buf);
        }
        exit(EXIT_SUCCESS);
    }

    c[1] = fork();
    if (c[1] < 0) {
        fprintf(stderr, "fork error");
        exit(EXIT_FAILURE);
    } else if (c[1] == 0) {
        // 第二个子进程:写入管道数据
        close(p[0]); // 关闭未使用的读端
        dup2(p[1], STDOUT_FILENO); // 安全替换标准输出
        close(p[1]); // 复制后关闭原描述符

        printf("HI");
        fflush(stdout); // 强制刷新缓冲区,确保数据立即写入管道
        exit(EXIT_SUCCESS);
    }

    // 父进程关闭管道所有描述符,避免持有写端导致子进程阻塞
    close(p[0]);
    close(p[1]);

    // 等待两个子进程结束,顺序不影响
    if (waitpid(c[0], NULL, 0) == -1 || waitpid(c[1], NULL, 0) == -1) {
        exit(EXIT_FAILURE);
    }

    return 0;
}

关键修复点说明

  • 父进程关闭管道描述符:父进程不使用管道,创建完子进程后立即关闭管道的读写描述符,确保第二个子进程退出后,管道写端完全关闭,第一个子进程的read()能正常读取数据并结束。
  • 用dup2()替代手动操作:dup2()可以安全替换文件描述符,避免手动关闭标准输入/输出后出错的情况。
  • 强制刷新输出缓冲区:调用fflush(stdout)确保"HI"不被缓冲,立即写入管道,让第一个子进程能及时读取到数据。
  • 检查read()返回值:避免读取失败或EOF时打印垃圾字符,手动添加字符串终止符保证输出格式正确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 07:35:38