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

使用pipe()系统调用连接两子进程标准IO的代码问题排查

管道进程通信问题排查与修复

思路正确性分析

你的核心思路没问题:父进程创建管道,先fork第一个子进程重定向标准输出到管道写端,再fork第二个子进程重定向标准输入到管道读端,实现进程间通信。但代码里有几个关键错误导致结果异常。

错误点与修复方案

1. 第二个子进程的管道端搞反了

你在第二个子进程里写的是:

dup2( pipe_name[1],STDIN_FILENO);

pipe_name[1]是管道的写端,但第二个子进程需要从管道读数据,得用管道的读端pipe_name[0],正确代码:

dup2(pipe_name[0], STDIN_FILENO);

2. 缓冲区定义和read调用完全错了

  • 你定义的char words;是单个字符,根本装不下要读的字符串,得改成数组:char words[1000];
  • read的第二个参数需要是接收数据的指针,你直接传words(字符值)会导致非法内存访问,应该传数组名(本质是指针)
  • 读取后要手动加字符串终止符\0,不然printf输出会乱码
  • 你用printf("%d", words)是按整数输出,要输出字符串得用%s

修复后的读取代码:

char words[1000];
ssize_t bytes_read = read(STDIN_FILENO, words, sizeof(words) - 1);
if (bytes_read > 0) {
    words[bytes_read] = '\0'; // 加终止符
}
printf("My sibling says:\n    %s\n", words);

3. 管道无用端未关闭(规范操作)

每个进程应该关掉不需要的管道端,避免管道引用计数不为0导致的异常:

  • 第一个子进程用了写端,关掉读端close(pipe_name[0]);
  • 第二个子进程用了读端,关掉写端close(pipe_name[1]);
  • 父进程在fork完两个子进程后,关掉管道两端close(pipe_name[0]); close(pipe_name[1]);

修复后的完整代码

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>

int main(int argc, char *argv[])
{   
    int pipe_name[2];
    printf("hello world (pid:%d)\n", (int) getpid());
    
    if(pipe(pipe_name) < 0){ 
        printf("mission failed! We'll gettem next time...\n");
        exit(1);
    } 

    int rc = fork();
    if (rc < 0) {
        fprintf(stderr, "fork failed\n");
        exit(1);
    } else if (rc == 0) {
        // 第一个子进程:重定向stdout到管道写端
        close(pipe_name[0]);
        dup2(pipe_name[1], STDOUT_FILENO);
        printf("hello, I am child (pid:%d)\n", (int) getpid());
        close(pipe_name[1]);
        exit(0);
    } else {
        wait(NULL);

        int rc2 = fork();
        if (rc2 < 0) {
            fprintf(stderr, "fork failed\n");
            exit(1);
        } else if (rc2 == 0) {
            // 第二个子进程:重定向stdin到管道读端
            close(pipe_name[1]);
            dup2(pipe_name[0], STDIN_FILENO);
            char words[1000];
            ssize_t bytes_read = read(STDIN_FILENO, words, sizeof(words) - 1);
            if (bytes_read > 0) {
                words[bytes_read] = '\0';
            }
            printf("My sibling says:\n    %s\n", words);
            close(pipe_name[0]);
            exit(0);
        } else { 
            // 父进程关闭管道两端
            close(pipe_name[0]);
            close(pipe_name[1]);
            wait(NULL);
            printf("hello, I am parent of %d (pid:%d)\n", rc2, (int) getpid());
        }
    }
    return 0;
}

修复后的预期输出

hello world (pid:xxxx)
hello, I am child (pid:xxxx)
My sibling says:
    hello, I am child (pid:xxxx)
hello, I am parent of xxxx (pid:xxxx)

内容的提问来源于stack exchange,提问作者Conan G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:03:11