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

为何子进程read函数未返回(预期返回-1)且printf函数失效?

问题分析与解决

咱们来一步步拆解你遇到的两个问题:子进程read一直阻塞不返回、printf没有正常输出。

1. 为什么read不返回-1反而一直阻塞?

管道的read返回-1(触发EOF)的核心前提是管道所有的写端都被关闭。你的代码里有两个关键错误导致了阻塞:

  • 子进程继承了管道的写端fd[1],但完全用不到这个描述符,也没有关闭它。这会让管道的写端始终处于“存在”状态,子进程的read会一直等待数据,不会触发EOF。
  • 父进程写完管道后,既没关闭自己的写端fd[1],还额外调用了read(fd[0])——但子进程根本没往管道写数据,且子进程的写端也没关闭,父进程的read自然也会卡住。

简单来说:管道的读写端没有按需关闭,导致所有read操作都卡在等待数据的状态。

2. 为什么printf无法正常工作?

不是printf功能有问题,是它根本没机会执行!不管子进程还是父进程,都是先调用read,而read已经阻塞住了,后面的printf代码根本没跑到。额外补充个知识点:printf是行缓冲机制,就算没阻塞,有时候也需要手动fflush(stdout)刷新,但在这个问题里,核心原因是代码根本没执行到printf那一步。

修正后的代码

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h> // 引入waitpid所需的头文件

int main() {
    int fd[2];
    pipe(fd);
    pid_t pid = fork();
    
    if(pid == 0) {
        // 子进程:关闭不需要的写端
        close(fd[1]);
        
        char buf[128] = {0};
        int ret = read(fd[0], buf, sizeof buf);
        printf("Son ret is %d\n", ret);
        write(STDOUT_FILENO, buf, ret);
        
        // 测试read返回-1的场景:读完现有数据后再读一次
        ret = read(fd[0], buf, sizeof buf);
        printf("Son second ret is %d\n", ret);
        
        // 读完后关闭读端
        close(fd[0]);
    } else if(pid > 0){
        // 父进程:关闭不需要的读端
        close(fd[0]);
        
        char buf[128] = "hello\n"; // 字符串字面量自带结束符,无需手动加\0
        // 写入实际有效字节数,而非整个buf的大小,避免写入多余的空字符
        write(fd[1], buf, strlen(buf));
        
        // 写完后立刻关闭写端,触发子进程的EOF
        close(fd[1]);
        
        // 等待子进程执行完毕,避免父进程先退出导致输出混乱
        waitpid(pid, NULL, 0);
        
        printf("Dad finished\n");
    }
    return 0;
}

关键修正说明

  • 按需关闭管道描述符:每个进程只保留自己需要的管道端,用不到的立刻关闭,这是管道编程的核心原则,能从根源避免阻塞问题。
  • 控制写入字节数:用strlen(buf)替代sizeof buf,只写入有效内容,避免把buf中多余的空字符写入管道。
  • 等待子进程结束:父进程通过waitpid等待子进程执行完再退出,避免输出顺序混乱或子进程变成僵尸进程。
  • 移除无用的read:父进程原本的read(fd[0])完全多余,因为子进程不会往管道写数据,只会导致阻塞,直接删除即可。

运行修正后的代码,你会看到子进程第一次read返回实际读取的字节数,第二次read就会返回-1,完全符合你的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:29:49