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 不再能够从管道中正确读取
我该如何解决这个问题?
【问题讨论】:
您将<string.h>
(甚至<cstring>
)与<string>
组合在一起,包括<iostream>
等。 using namespace std;
让情况变得更糟。不要这样做。你在制造问题。接下来,您将 C 与 C++ 结合起来。也不要那样做。 C++ 有fstream
s,你应该使用它。
这段代码不会被编译。那么真正的代码在哪里?
我刚刚用 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 启动服务
SoapUI 5.6.0 无法在 Ubuntu 20.04 LTS 上安装