我目前正在實施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