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

Ubuntu 20.04下fgets无法二次读取命名管道内容问题咨询

问题解答

1. 代码失效原因

该问题不是发行版基础库变更导致fgets本身功能异常,核心原因是命名管道的I/O特性和C标准文件流的EOF状态处理规则:

  • 每次你执行echo "message" >> /tmp/pipe写入数据时,echo进程会临时打开管道写入端,写完数据后进程退出,此时管道的所有写入端被关闭,读取端的fgets读完当前数据后会触发EOF,返回NULL,同时会给result_pipe_stream设置EOF错误标志。
  • 按照C标准规定,文件流一旦被标记了EOF/错误状态,后续所有读操作都会直接返回失败,除非手动清除该标志。
  • Ubuntu 18.04携带的glibc 2.27版本对管道这类特殊文件的EOF标志处理存在非标准兼容逻辑,当管道有新写入端连接时会自动重置标志,而Ubuntu 20.04使用的glibc 2.31版本修复了这个不符合标准的行为,因此原有代码无法正常运行。

2. 可行解决方案

可根据使用场景选择以下任意一种方案:

  • 方案1:手动清除流错误标志
    每次fgets返回NULL时调用clearerr()清除流的错误标志,再加短休眠避免空转占用CPU。需要注意使用该方案要提前引入<unistd.h>头文件,修改后的read_result_from_pipe函数逻辑如下:
    string read_result_from_pipe(){
        if (result_pipe_stream == NULL){
            printf("\n[BINDING-COMMONS] ERROR: Pipe is not set");
            return "";
        }
        
        std::stringstream oss;
        while (1) {
            char buf[BUFSIZ];
            if( fgets (buf, BUFSIZ, result_pipe_stream) != NULL ) {
                int buflen = strlen(buf);
                if (buflen >0){
                    if (buf[buflen-1] == '\n'){
                            buf[buflen-1] = '\0';
                            oss << buf;
                            return oss.str();
                    } else {
                        oss << buf;
                        // line was truncated. Read another block to complete line.
                    }
                }
            } else {
                clearerr(result_pipe_stream);
                usleep(10000); // 休眠10ms
            }
        }   
    }
    
  • 方案2:以读写模式打开管道
    修改main函数中fopen的打开模式,从只读"r"改为读写"r+",让进程自身持有管道的写入端,只要进程不退出,管道就永远不会出现所有写入端关闭的情况,也就不会触发EOF状态,读不到数据时fgets会主动阻塞等待新数据写入,无需额外处理错误标志:
    int main(int argc, char *argv[]){
        result_pipe_stream = fopen("/tmp/pipe" , "r+");
        while (1){
            cout << read_result_from_pipe() << '\n';
        }
    }
    
  • 方案3:改用底层系统调用
    替换C标准库的文件流接口,直接使用open/read系统调用读取管道,底层系统调用不会保留EOF状态,每次读取都会直接尝试从管道获取数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 06:15:04