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

Open an ifstream on a pipe with no data without blocking

本文关键字:ifstream 数据 管道      更新时间:2023-10-16

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

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

当我运行程序时,它在ifstream构造函数中阻塞。我看到"Opening name"打印到控制台上,但是没有显示已打开的语句。

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

$ echo foo > name

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

在管道的读端调用open会阻塞,直到写端打开。

您可以使用O_NONBLOCK标志来打开管道的文件描述符,但是没有标准的方法来使用fd和std::ifstream,见这里。

猜测您的需求,我会说一个打开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
};
}

由于通过ifstream块打开输入管道,直到有人向它写入,您总是可以让ifstream块。然后从另一个线程解除阻塞,创建自己的ofstream到同一管道,然后立即关闭ofstream。这将解锁ifstream并将其标记为eof。这比使用特定于平台的文件句柄控件要容易得多,也更不容易出错。

实际上您可以在命名管道上打开std::ifstream而不阻塞写入器,但是您必须设置标志,好像您也要写入流。

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