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

独立文件进程间管道通信故障排查求助

管道进程通信问题:P1发送的十六进制数据P2接收不到

问题描述

我在大型项目中需要实现两个进程通过管道通信:P1生成50到99的数字,转为十六进制后通过管道发送给P2,P2负责打印该数字。但目前仅能打印P1 generated: xxx,P2完全没有输出,尝试多种方法都没解决,请求协助排查错误。

原代码片段

pipe1.c

#define WRITE 1
#define READ 0
int main() {
 int i;
 char hex[30];
 int my_pipe[2];
 pipe(my_pipe);
 int var;
 close(my_pipe[READ]);
 for(i=50;i<100;i++){
 printf("P1 generated: %d\n",i);
 sprintf(hex, "%x", i);
 write(my_pipe[WRITE], &hex, sizeof(hex));
 printf("P1 in hex %s\n",hex);
 sleep(3);
 }
 return 0;
}

pipe2.c

#define WRITE 1
#define READ 0
int main() {
 char hex[30];
 int my_pipe2[2];
 pipe(my_pipe2);
 int var;
 close(my_pipe2[WRITE]);
 for(;;){
 read(my_pipe2[READ], &hex, sizeof(hex));
 printf("P2 received: %s",hex);
 sleep(3);
 }
 return 0;
}

主启动代码

int main(int argc, char *argv[]) {
 //.....
 if (fork() == 0) {
 execlp("./pipe1", "./pipe1", NULL);
 }
 sleep(1);
 if (fork() == 0) {
 execlp("./pipe2", "./pipe2", NULL);
 }
 sleep(1);
 //....
}

问题根源分析

你遇到的核心问题是两个子进程使用的是完全独立的管道,根本没有建立起通信链路:

  • pipe1.c里自己创建了一个管道,往这个管道写数据;
  • pipe2.c里也自己创建了另一个完全无关的管道,从这个空管道读数据;
  • 主进程创建的两个子进程完全不知道对方的存在,自然无法通信。

另外还有两个次要问题:

  1. write和read里的&hex是多余的——hex作为数组名本身就是指向数组首元素的指针,不需要取地址;
  2. P2的printf没有加换行符\n,会导致输出被标准输出缓冲,即使收到数据也可能看不到。

修正后的完整解决方案

我们需要让主进程创建共享管道,然后将管道的文件描述符传递给两个子进程,这样它们才能使用同一个管道进行读写。

1. 修正主启动代码

主进程先创建管道,然后把管道的写端传给P1,读端传给P2:

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

#define WRITE 1
#define READ 0

int main(int argc, char *argv[]) {
    int my_pipe[2];
    // 创建管道,失败则报错
    if (pipe(my_pipe) == -1) {
        perror("Failed to create pipe");
        return 1;
    }

    // 启动P1:负责写数据
    if (fork() == 0) {
        close(my_pipe[READ]); // P1不需要读端,关闭
        char write_fd_str[10];
        snprintf(write_fd_str, sizeof(write_fd_str), "%d", my_pipe[WRITE]);
        // 将管道写端fd作为参数传给pipe1
        execlp("./pipe1", "./pipe1", write_fd_str, NULL);
        perror("Failed to start pipe1");
        exit(1);
    }

    sleep(1);

    // 启动P2:负责读数据
    if (fork() == 0) {
        close(my_pipe[WRITE]); // P2不需要写端,关闭
        char read_fd_str[10];
        snprintf(read_fd_str, sizeof(read_fd_str), "%d", my_pipe[READ]);
        // 将管道读端fd作为参数传给pipe2
        execlp("./pipe2", "./pipe2", read_fd_str, NULL);
        perror("Failed to start pipe2");
        exit(1);
    }

    // 主进程不再需要管道两端,关闭它们
    close(my_pipe[READ]);
    close(my_pipe[WRITE]);

    // 等待两个子进程结束
    wait(NULL);
    wait(NULL);

    return 0;
}

2. 修正pipe1.c

接收主进程传递的管道写端fd,用这个fd写数据:

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

#define WRITE 1
#define READ 0

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <pipe-write-fd>\n", argv[0]);
        return 1;
    }

    // 将命令行参数转为整数型文件描述符
    int write_fd = atoi(argv[1]);
    int i;
    char hex[30];

    for(i=50;i<100;i++){
        printf("P1 generated: %d\n",i);
        sprintf(hex, "%x", i);
        // 直接用传入的fd写数据,hex不需要&
        write(write_fd, hex, sizeof(hex));
        printf("P1 sent hex: %s\n", hex);
        sleep(3);
    }

    // 写完后关闭写端,通知P2没有数据了
    close(write_fd);
    return 0;
}

3. 修正pipe2.c

接收主进程传递的管道读端fd,用这个fd读数据,并处理管道关闭的情况:

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

#define WRITE 1
#define READ 0

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <pipe-read-fd>\n", argv[0]);
        return 1;
    }

    // 将命令行参数转为整数型文件描述符
    int read_fd = atoi(argv[1]);
    char hex[30];

    while(1){
        ssize_t bytes_read = read(read_fd, hex, sizeof(hex));
        if (bytes_read <= 0) {
            // 管道写端已关闭(P1结束),退出循环
            break;
        }
        // 添加\n确保输出立即刷新到终端
        printf("P2 received: %s\n", hex);
        sleep(3);
    }

    // 关闭读端
    close(read_fd);
    return 0;
}

关键修正点说明

  1. 共享管道创建:管道由主进程创建,两个子进程继承或接收管道的fd,确保它们使用同一个通信通道;
  2. 关闭无用管道端:每个进程只保留自己需要的管道端,避免管道被意外保持打开导致的阻塞;
  3. 处理管道关闭:P2检测到read返回<=0时,知道P1已经结束,退出循环,避免无限阻塞;
  4. 修复输出缓冲:给P2的printf添加\n,确保输出立即显示在终端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:42:02