为啥我在使用 ifstream 通过命名管道读取一行后得到 EOF?

Posted

技术标签:

【中文标题】为啥我在使用 ifstream 通过命名管道读取一行后得到 EOF?【英文标题】:Why do I get EOF after reading one line thourgh a named pipe using ifstream?为什么我在使用 ifstream 通过命名管道读取一行后得到 EOF? 【发布时间】:2015-03-30 20:35:29 【问题描述】:

在命令行中,我使用 mkfifo 创建了一个管道并确认该文件存在。 ls -al 给:

prw-r--r--    1 user  group      0 Mar 30 11:52 my_pipe

然后我使用此代码尝试从该管道中逐行读取文本:

ifstream pipe("/path/to/my_pipe");
string message;
while(getline(pipe, message) && message != "EXIT")

    cout << boolalpha << pipe.good() << endl << pipe.eof() << endl << pipe.bad() << endl;


cout << boolalpha << pipe.good() << endl << pipe.eof() << endl << pipe.bad() << endl;

回到命令行我做echo "banana" &gt; my_pipe 然后程序存在,输出如下:

true
false
false
false
true
false

这表明在读取banana 后流处于良好状态,但在第二次调用getline 时我点击EOF 并退出。

为什么我点击了EOF,在我阅读我的特殊EXIT 消息之前,我可以做些什么来保持流的阅读并处于良好状态?

编辑:

结论:

    使用fstream 而不是ifstream。 在撰写本文时,libc++ 中显然存在一个关于 fstream 和管道的错误。

【问题讨论】:

【参考方案1】:

当管道被所有打开它以进行写入的进程关闭时,EOF 发生在管道上。在您的示例中,打开它进行写入的唯一进程是 echo 命令;当它退出时,它会关闭管道,导致读取过程中出现EOF。

如果您希望管道在每个写入它的客户端之间保持打开状态,那么方法就是以读写模式打开管道。这样,读过程也是写过程,只要管道打开,就不会被所有的写者关闭。

fstream pipe("/path/to/my_pipe");

或者,您可以通过在单个重定向进程中执行多个命令来保持发送端的管道打开:

( echo banana ; echo EXIT ) > my_pipe

【讨论】:

我尝试了一个普通的fstream,但它永远不会从getline返回。顺便说一句,ios::in|ios::outfstream 的默认模式,所以这有点多余。 只要有人写了一行,它就会从getline返回。在那之前,它应该等待。不过,它永远不会离开循环。 我添加了一个答案,显示如何在 echo 命令之间保持管道打开。 是的,它“应该”从getline 返回,但它只是没有。适合你吗?这是我的实现中的错误吗?另外,我希望这个程序能够长期存在,而不仅仅是一次性收听一些回声的字符串。 我刚刚测试过了。我在一个窗口中启动程序,然后转到另一个窗口并执行echo foo &gt; my_pipe。第一个窗口打印true false false

以上是关于为啥我在使用 ifstream 通过命名管道读取一行后得到 EOF?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 c++ ifstream 不能从设备读取?

为啥我不能使用 ifstream 读取撇号而不崩溃?

为啥在没有人阅读后继续写入命名管道?

通过重叠 IO 的异步命名 Windows 管道通信

为啥这里举例说明在 LINUX 中使用命名管道 -FIFO 的程序会遇到竞争条件?

在断开连接之前等待读取命名管道