fgets 无法在 Ubuntu 20.04 上从管道读取两次

Posted

技术标签:

【中文标题】fgets 无法在 Ubuntu 20.04 上从管道读取两次【英文标题】:fgets not able to read from pipe twice on Ubuntu 20.04 【发布时间】:2021-10-21 12:41:41 【问题描述】:

我有以下曾经在 Ubuntu 18.04 上工作的代码。现在,我在 Ubuntu 20.04 中编译并运行它,但由于某种原因,代码停止工作。

代码旨在从命名管道中读取。为了测试它,我使用mkfifo /tmp/pipe 创建管道,然后使用echo "message" >> /tmp/pipe 写入管道。

fgets()方法第一次执行时,函数从管道返回期望值;但是从第二次调用开始,该方法返回NULL,即使我执行了几个回显命令,代码也会卡在循环中。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <sstream>
#include <fstream>
#include <limits>
#include <iomanip>

#include <iostream>
#include <cstdlib>

using namespace std;

FILE* result_pipe_stream;

string read_result_from_pipe()
    if (result_pipe_stream == NULL)
        printf("\n[BINDING-COMMONS] ERROR: Pipe is not set");
        return NULL;
    
    
    
    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.
                
            
        
       


int main(int argc, char *argv[])
    result_pipe_stream = fopen("/tmp/pipe" , "r");
    while (1)
        cout << read_result_from_pipe() << '\n';
    


    为什么代码不再工作了?我假设某些库在发行版中发生了变化,并且 fgets 不再能够从管道中正确读取 我该如何解决这个问题?

【问题讨论】:

您将&lt;string.h&gt;(甚至&lt;cstring&gt;)与&lt;string&gt; 组合在一起,包括&lt;iostream&gt; 等。 using namespace std; 让情况变得更糟。不要这样做。你在制造问题。接下来,您将 C 与 C++ 结合起来。也不要那样做。 C++ 有fstreams,你应该使用它。 这段代码不会被编译。那么真正的代码在哪里? 我刚刚用 g++ ¬¬u 编译了该代码 @chux-ReinstateMonica 就是这样。我刚刚添加了一个 clearer(result_pipe_stream),现在我收到了消息。可能我应该检查错误并在清除它之前处理每种情况下的操作。谢谢 @FrancescLordan BTW,如果管道数据包含 null 字符,则这种读取方法需要重新处理以区分读取的 null 字符从附加的fgets() 适用。我会考虑 fread() 或更多类似 C++ 的选项。 【参考方案1】:

if( fgets (buf, BUFSIZ, result_pipe_stream) != NULL ) --> 一旦fgets() 由于文件结束返回NULL,它将在后续调用中继续返回NULL不读取,除非 result_pipe_stream 的文件结束指示符 被清除 - 就像 clearerr() 一样。代码陷入无限循环,不再阅读,它应该

真正的问题是为什么它在 Ubuntu 18.04 中“有效”。我怀疑那个版本不合规。

while (1) 
    char buf[BUFSIZ];
    if( fgets (buf, BUFSIZ, result_pipe_stream) != NULL ) 
      ...
    
     // Perhaps assess why here, end-of-file, input error, too often here, ...
    clearerr(result_pipe_stream); // add

【讨论】:

Francesc Lordan,可能是旧版本的管道,在设置文件结束指示符后由于没有数据,清除了文件结束指示符 当新数据稍后到达时。 IMO,那将是不合规的。一旦设置了文件结束指示符,它只能在指定条件下被清除。

以上是关于fgets 无法在 Ubuntu 20.04 上从管道读取两次的主要内容,如果未能解决你的问题,请参考以下文章

无法在 linux ubuntu 20.04 中安装 libgraph

无法在 WSL 2 Ubuntu20.04 上通过 Ansible 启动服务

无法登录 Ubuntu 20.04 LTS [关闭]

SoapUI 5.6.0 无法在 Ubuntu 20.04 LTS 上安装

无法在 ubuntu 20.04 上通过 apt 安装 curl

Ubuntu20.04虚拟机扩展磁盘后系统无法启动