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

单进程将stdout重定向到pipe后读取时read调用挂起问题咨询

问题原因分析

标准IO库的缓冲机制是触发挂起的核心原因:

  • C标准库的printf属于标准IO函数,默认对终端类设备采用行缓冲策略,只有遇到换行符、缓冲区满、主动调用fflush、程序正常退出这几种场景,才会把用户态缓冲区的数据刷入内核对应的文件描述符。你代码里的printf(in)输出的是不带换行符的qwerty,数据始终停留在用户态的stdout缓冲区,根本没写入pipe,内核的pipe通道里没有可用数据,read调用自然会一直阻塞等待。
  • 你后续测试用的write版本代码能正常运行,是因为write是系统调用,直接把数据提交给内核,绕过了用户态的标准IO缓冲,数据直接进入pipe,所以read可以正常读到内容。
  • 你注释掉的fsync(1)不生效的原因也很明确:fsync是针对内核态缓存的刷入操作,管不到用户态的标准IO缓冲区,调用时数据还没进入内核空间,自然不会有任何效果。
修复方案

只需要在printf调用之后新增一行fflush(stdout),强制把用户态缓冲区的数据刷入pipe对应的内核空间即可,修复后的完整代码如下:

#include <stdio.h>
#include <unistd.h>
const char in[7] = "qwerty";

int main ()
{
    int fds[2], stdout_sav;
    char str[8] = {0};
    pipe(fds);
    if ((stdout_sav = dup(1)) < 0) return 1;  // save stdout
    if (dup2(fds[1], 1) < 0) return 2;   // stdout -> pipe
    close(fds[1]);

    if (printf(in) <= 0) return 3;
    fflush(stdout); // 新增行:刷入标准IO缓冲区到内核
    read(fds[0], str, sizeof(in));
    close(fds[0]);
    if (dup2(stdout_sav, 1) < 0) return 4;   // restore stdout
    close(stdout_sav);

    printf("Received %s\n", str);
    return 0;
}

编译运行后即可正常输出Received qwerty。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:36:03