21

我想确保已将 ofstream 写入磁盘设备。这样做的可移植方式(在 POSIX 系统上可移植)是什么?

open如果我在只读附加模式下单独文件以获取文件描述符并使用它调用,这是否解决了问题fsync?像这样:

ofstream out(filename);
/* ...
   write content into out
   ...
*/
out.close();

int fd = open(filename, O_APPEND);
fsync(fd);
close(fd);
4

4 回答 4

10

如果您能够使用 Boost,请尝试使用基于 file_descriptor_sink 的流,例如:

boost::filesystem::path filePath("some-file");
boost::iostreams::stream<boost::iostreams::file_descriptor_sink> file(filePath);

//  Write some stuff to file.

//  Ensure the buffer's written to the OS ...
file.flush();

//  Tell the OS to sync it with the real device.
//
::fdatasync(file->handle());
于 2014-05-23T10:11:04.387 回答
5

不幸的是,通过标准查看,没有提供任何类模板basic_filebuf或任何basic_[io]?fstream类模板来允许您提取底层 OS 文件描述符(以fileno()C stdio I/O 的方式)。

也没有open()将这样的文件描述符作为参数的方法或构造函数(这将允许您使用不同的机制打开文件并记录文件句柄)。

basic_ostream::flush(),但是我怀疑这实际上并没有调用fsync()- 我希望,就像fflush()在 stdio 中一样,它只确保用户空间运行时库缓冲区被刷新,这意味着操作系统仍然可以缓冲数据。

所以简而言之,似乎没有办法做到这一点。:(

该怎么办?我的建议是子类化basic_filebuf<C, T>

template <typename charT, typename traits = std::char_traits<charT> >
class my_basic_filebuf : public basic_filebuf<charT, traits> {
    ....

public:
    int fileno() { ... }
    ....
};

typedef my_basic_filebuf<char> my_filebuf;

要使用它,您可以ofstream使用默认构造函数构造一个,然后分配新缓冲区rdbuf()

my_filebuf buf;
buf.open("somefile.txt");

ofstream ofs;
ofs.rdbuf(&buf);

ofs << "Writing to somefile.txt..." << endl;
int fd = static_cast<my_filebuf*>(ofs.rdbuf())->fileno();

当然,您也可以派生一个新类 frombasic_ostream以使打开文件和检索其文件描述符的过程更加方便。

于 2009-03-24T13:02:11.343 回答
3

std::filebuf可能在其中的某处有一个文件描述符,但要获得它需要可怕的特定于实现的黑客攻击。

这是针对 libstdc++ 的一个如此可怕的 hack。

#include <fstream>
#include <unistd.h>

int GetFileDescriptor(std::filebuf& filebuf)
{
  class my_filebuf : public std::filebuf
  {
  public:
    int handle() { return _M_file.fd(); }
  };

  return static_cast<my_filebuf&>(filebuf).handle();
}

int main()
{
  std::ofstream out("test");

  out << "Hello, world!";
  out.flush();

  fsync(GetFileDescriptor(*out.rdbuf()));
}
于 2015-02-10T18:25:36.050 回答
2

您根本无法fsync()对打开以供读取的文件描述符进行可移植的操作。在 Linux 中,如果描述符未处于写入模式,fsync()记录为生成 EBADF。

于 2009-03-24T10:22:41.243 回答