【发布时间】:2021-06-21 15:51:40
【问题描述】:
我需要一种方法来检查文件(fifo)上是否有数据要以非阻塞方式读取。
我试过使用peek;但它是阻塞的,我尝试get 然后unget 一个字符,以便在不更改内容的情况下检查文件;但是get 再次被阻止...
我发现的唯一非阻塞解决方案是使用std::getline(file, line_str) 并检查字符串是否为空;但是,这 不 适合我的需要,因为它会更改文件中的数据。 (数据是一个序列化的对象,一旦我检测到有要读取的内容,我就会读取)。
注意:我需要它是非阻塞的:我有多个文件流,需要定期检查所有文件流以查看是否有要读取/反序列化的对象。
这是我想要实现的一个简单示例:
Sender.cpp:
#include <fstream>
#include <iostream>
#include <string>
extern "C"{
#include <sys/stat.h> // S_IRUSR, S_IWUSR, mkfifo
}
#include <cerrno> // errno
int main(int, char** argv) {
std::string pipe = "foobar";
if(mkfifo(pipe.c_str(), S_IRUSR | S_IWUSR) < 0){
if (errno != EEXIST){
std::cerr << errno;
}
}
std::ofstream file{pipe.c_str()};
file.write("boop", 4); // Simulated object serialization
}
Reader.cpp:
#include <fstream>
#include <iostream>
#include <string>
extern "C"{
#include <sys/stat.h> // S_IRUSR, S_IWUSR, mkfifo
}
#include <cerrno> // errno
int main(int, char** argv) {
std::string pipe = "foobar";
if(mkfifo(pipe.c_str(), S_IRUSR | S_IWUSR) < 0){
if (errno != EEXIST){
std::cerr << errno;
}
}
std::ifstream file{pipe.c_str()};
// ...
/* Do check for data and read/deserialize if any data */
// This is in some sort of loop that goes over the different
// filestreams and checks to see if they have data to treat
}
非常感谢任何帮助...
编辑:
按照 Zoso 的回答,我尝试使用文件大小来确定文件是否已更改;但是尝试获取 fifo 命名管道的大小是不可能的: filesystem error: cannot get file size: Operation not supported [myFilePath]
【问题讨论】:
-
非阻塞 I/O 对于 C++ 流来说并不简单。如果可以检索文件描述符,则可以使用
select/poll。这涉及一些黑客行为。或者,您可以直接使用 POSIX I/O,这将允许您select/poll。 -
如果你能得到FD你可以使用
ioctl(...FIONREAD). -
@P.P +1 用于 poll 和 C,但不幸的是我将使用 boost 进行序列化并且使用文件描述符有点痛苦......
标签: c++ file nonblocking ostream