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

C语言管道读取失败求助:无法从管道读取数据

问题分析与修复

你的管道代码存在几个关键问题,导致无法正常工作:

1. 管道读写端完全搞反

pipe() 函数创建的文件描述符数组中,pip[0] 是读端,pip[1] 是写端。你现在的代码错误地向读端(pip[0])写入,从写端(pip[1])读取,这直接导致数据无法正确传输。

2. 未处理字符串终止符

read() 函数不会自动在读取的缓冲区末尾添加 \0,而你的 log() 函数用 strlen() 计算长度,会因为找不到终止符而读取到随机内存内容,甚至引发未定义行为。

3. 管道使用的额外注意事项(含fork场景)

  • 单进程使用管道时:写完数据后必须关闭写端,否则 read() 会一直阻塞等待更多数据(系统认为写端还可能发送数据)。
  • 多进程(fork)场景:父/子进程必须关闭不需要的管道端。比如父进程写就关闭读端,子进程读就关闭写端,全部操作完成后再关闭剩余的端,否则可能导致管道无法正确触发EOF。

修正后的代码示例(单进程场景)

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

#define ERR -1
#define ERR_PIPE "Pipe creation failed"

void logn(const char* msg) {
    write(1, msg, strlen(msg));
    write(1, "\n", 1);
}

void log(const char* msg) {
    write(1, msg, strlen(msg));
}

int main() {
    int pip[2];

    if (pipe(pip) < 0) {
        logn(ERR_PIPE);
        return ERR;
    }

    char* buffer;
    // asprintf会自动分配内存,包含终止符
    asprintf(&buffer, "%d, Hi\n", 11);
    // 向写端pip[1]写入数据
    write(pip[1], buffer, strlen(buffer));
    free(buffer);
    // 关闭写端,让read知道没有更多数据
    close(pip[1]);
        
    char buffer2[32];
    // 从读端pip[0]读取数据
    ssize_t bytes_read = read(pip[0], buffer2, sizeof(buffer2)-1);
    if (bytes_read > 0) {
        // 添加终止符,避免strlen出错
        buffer2[bytes_read] = '\0';
        log(buffer2);
    }
    // 关闭读端
    close(pip[0]);

    return 0;
}

修正后的fork场景示例

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

#define ERR -1
#define ERR_PIPE "Pipe creation failed"

void logn(const char* msg) {
    write(1, msg, strlen(msg));
    write(1, "\n", 1);
}

void log(const char* msg) {
    write(1, msg, strlen(msg));
}

int main() {
    int pip[2];

    if (pipe(pip) < 0) {
        logn(ERR_PIPE);
        return ERR;
    }

    pid_t pid = fork();
    if (pid < 0) {
        logn("Fork failed");
        return ERR;
    }

    if (pid == 0) {
        // 子进程:读取管道,关闭写端
        close(pip[1]);
        char buffer2[32];
        ssize_t bytes_read = read(pip[0], buffer2, sizeof(buffer2)-1);
        if (bytes_read > 0) {
            buffer2[bytes_read] = '\0';
            log(buffer2);
        }
        close(pip[0]);
        exit(0);
    } else {
        // 父进程:写入管道,关闭读端
        close(pip[0]);
        char* buffer;
        asprintf(&buffer, "%d, Hi\n", 11);
        write(pip[1], buffer, strlen(buffer));
        free(buffer);
        close(pip[1]);
        // 等待子进程完成
        wait(NULL);
    }

    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 13:41:19