我目前正在实施ping/pong缓冲方案来安全地将文件写入磁盘。我在Linux/CentOS机器上使用C++/Boost。现在我面临的问题是强制将文件实际写入磁盘。不管文件系统的所有缓存策略(ext3/ext4)/ SO自定义规则/ RAID控制器/硬盘控制器,是否可以这样做?强制将文件写入磁盘
最好是使用普通的fread()/ fwrite(),C++ ostream或boost文件系统吗?
我听说,只是冲洗出来的文件(fflush())并不能保证实际写入
谢谢!
我目前正在实施ping/pong缓冲方案来安全地将文件写入磁盘。我在Linux/CentOS机器上使用C++/Boost。现在我面临的问题是强制将文件实际写入磁盘。不管文件系统的所有缓存策略(ext3/ext4)/ SO自定义规则/ RAID控制器/硬盘控制器,是否可以这样做?强制将文件写入磁盘
最好是使用普通的fread()/ fwrite(),C++ ostream或boost文件系统吗?
我听说,只是冲洗出来的文件(fflush())并不能保证实际写入
谢谢!
fflush(用于FILE *),std :: flush(用于IOStream)强制程序发送到操作系统。
POSIX有
同步(2)要求安排写其缓冲区,但可以写入完成之前返回(Linux正在等待数据是在返回前发送到硬件)。 (2)这是保证等待数据发送到硬件,但需要一个文件描述符(你可以从FILE *获得一个fileno(3),我知道没有标准的方式从IOStream获得一个)。
O_SYNC作为打开标志(2)。
在所有情况下,硬件可以有它自己的缓冲区(但如果上有控制,良好的实现将尝试也刷新他们ISTR一些磁盘使用电容器,使他们能够清除发生的任何事情)和网络文件系统有他们自己的警告。
不是标准的C++。您必须使用某种系统特定的 IO,例如open
,在Unix下为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);
}
(这只是表面测试过的,但基本思路就是这样。)
您可以使用fsync()/ fdatasync() ce(注1)将数据存入存储器。 这些请求文件描述符,例如,打开()。 linux manpage有更多的linux特定的信息,特别是在fsync和fdatasync的区别。
如果您不直接使用文件描述符,许多抽象将包含驻留在您的过程中的内部缓冲区。
例如如果您使用FILE *,则必须首先将数据从应用程序中清除。
//... open and write data to a FILE *myfile
fflush(myfile);
fsync(fileno(myfile));
fclose()呢?我们需要它吗? –
@G_G当你完成文件*,关闭文件,然后使用fclose() – nos
对不起,我的意思是当直接使用文件描述符;我们是否需要明确的关闭(fd)呼叫? –
而对于C++流,操作符是'std :: flush'而不是'fflush'。 –
谢谢!所以我必须强制我的程序首先提交文件系统(fflush/flush),然后强制SO将其提交到磁盘控制器(sync)。你能告诉我一些概念验证码吗? –
@JoachimPileborg,这就是我打算用太简洁(f)冲洗来表示的,我澄清了。 – AProgrammer