在管道上打开ifstream,没有数据而没有阻塞

时间:2013-03-04 23:18:29

标签: c++ named-pipes fstream ifstream

我正在尝试使用ifstream来打开一个最终将数据写入其中的命名管道。

std::cout << "Opening " << name << std::endl;
std::ifstream manual_shutdown_file(name.c_str());
std::cout << "Opened " << name << std::endl;

当我运行程序时,它会在ifstream构造函数中阻塞。我看到“打开名称”打印到控制台,但打开的语句没有出现。

我知道我正在连接管道,因为如果我执行

$ echo foo > name
从shell获取

,然后构造函数返回并打印Opened语句。即使我不想立即尝试读取数据,也没有办法打开管道,直到它有数据吗?

3 个答案:

答案 0 :(得分:2)

在管道的读取端调用open将阻塞,直到写入结束打开。

您可以使用O_NONBLOCK标志打开管道的文件描述符,但没有标准方法可以将fd用于std::ifstreamsee here.

根据你的要求猜测,我会说一个打开fd并提供轮询信号接口的小类适合,例如:

namespace blah
{
class signal_t
{
private:
   int fd;

   // note: define sensible copy/move semantics
   signal_t(const signal_t&) = delete;
   signal_t& operator=(const signal_t&) = delete;
public:
   signal_t(const char* named_pipe);   // open fd, set O_NONBLOCK

   void notify() const;                // write 1 byte to fd as signal
   bool poll() const;                  // attempt to read from fd, return true if signalled.

   ~signal_t();                        // close fd
};
}

答案 1 :(得分:0)

由于通过ifstream块打开了输入管道,直到有人对其进行写入为止,所以您总是可以放任ifstream块。然后要将其从另一个线程中解除阻止,请创建您自己的ofstream到同一管道,然后立即关闭ofstream。这将取消阻止ifstream并将其标记为eof。与弄乱特定于平台的文件句柄控件相比,这要容易得多,并且不易出错。

答案 2 :(得分:-1)

实际上,您可以在命名管道上打开std::ifstream而不会阻止编写器,但您必须设置这些标志,就像您还要写入流一样。

尝试std::ifstream pipe_stream(filename, std::ifstream::in | std::ifstream::out)stream.open(filename, std::ifstream::in | std::ifstream::out)