我正在尝试使用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语句。即使我不想立即尝试读取数据,也没有办法打开管道,直到它有数据吗?
答案 0 :(得分:2)
在管道的读取端调用open
将阻塞,直到写入结束打开。
您可以使用O_NONBLOCK
标志打开管道的文件描述符,但没有标准方法可以将fd用于std::ifstream
,see 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)
。