强制将文件写入磁盘

我目前正在执行ping / pong缓冲scheme来安全地将文件写入磁盘。 我在Linux / CentOS机器上使用C ++ / Boost。 现在我面临的问题,迫使文件实际写入磁盘。 不pipe文件系统的所有caching策略(ext3 / ext4)/ SO自定义规则/ RAID控制器/硬盘控制器,是否可以这样做?

最好使用普通的fread()/ fwrite(),c ++ ostream或boost文件系统?

我听说只是刷新文件(fflush())并不能保证实际的写入

谢谢!

Solutions Collecting From Web of "强制将文件写入磁盘"

fflush(对于FILE *),std :: flush(对于IOStream)来强制你的程序发送到操作系统。

POSIX有

  • 同步(2)要求定时写入其缓冲区,但可以在写入完成之前返回(Linux正在等待数据发回到硬件前)。

  • fsync(2)保证等待数据发送到硬件,但是需要一个文件描述符(你可以用fileno(3)从FILE *获得一个,我知道没有标准的方法来从一个文件的iostream)。

  • O_SYNC作为打开标志(2)。

在所有情况下,硬件可能都有它自己的缓冲区(但是如果它有控制权的话,一个好的实现将会尝试刷新它们,ISTR表示一些磁盘正在使用电容器,以便它们能够冲刷电源发生的任何事情)和网络文件系统有自己的警告。

您可以使用fsync ()/ fdatasync ()强制(注1)将数据存储到存储上。 那些请求文件描述符,例如open()。 Linux手册页有更多的Linux特定的信息,特别是在fsync和fdatasync的区别。

如果不直接使用文件描述符,许多抽象将包含驻留在进程中的内部缓冲区。

例如,如果您使用FILE *,则必须首先从应用程序中清除数据。

 //... open and write data to a FILE *myfile fflush(myfile); fsync(fileno(myfile)); 
  • 注1:这些调用强制操作系统确保任何OS高速缓存中的任何数据写入驱动器,并且驱动器确认这一事实。 许多硬盘驱动器在操作系统中都会涉及到这一点,并可能将数据填充到驱动器上的高速缓存中。

不在标准的C ++中。 你将不得不使用某种系统特定的IO,比如在Unix下open O_SYNC标志,然后write

请注意,这是部分隐含的事实, ostream (和C, FILE* )被缓冲。 如果不确切地知道什么时候写入磁盘,那么坚持写入的事务完整性就没有什么意义。 (不过,设计一个在你做显式刷新时才写入的streambuf并不难)。

编辑:

举一个简单的例子:

 class SynchronizedStreambuf : public std::streambuf { int myFd; std::vector<char> myBuffer; protected: virtual int overflow( int ch ); virtual int sync(); public: SynchronizedStreambuf( std::string const& filename ); ~SynchronizedStreambuf(); }; int SynchronizedStreambuf::overflow( int ch ) { if ( myFd == -1 ) { return traits_type::eof(); } else if ( ch == traits_type::eof() ) { return sync() == -1 ? traits_type::eof() : 0; } else { myBuffer.push_back( ch ); size_t nextPos = myBuffer.size(); myBuffer.resize( 1000 ); setp( &myBuffer[0] + nextPos, &myBuffer[0] + myBuffer.size() ); return ch; } } int SynchronizedStreambuf::sync() { size_t toWrite = pptr() - &myBuffer[0]; int result = (toWrite == 0 || write( myFd, &myBuffer[0], toWrite ) == toWrite ? 0 : -1); if ( result == -1 ) { close( myFd ); setp( NULL, NULL ); myFd = -1; } else { setp( &myBuffer[0], &myBuffer[0] + myBuffer.size() ); } return result; } SynchronizedStreambuf::SynchronizedStreambuf( std::string const& filename ) : myFd( open( filename.c_str(), O_WRONLY | O_CREAT | O_SYNC, 0664 ) ) { } SynchronizedStreambuf::~SynchronizedStreambuf() { sync(); close( myFd ); } 

(这只是表面测试,但基本的想法是在那里。)