我正在用C++實現一些文件系統。到目前爲止,我使用的是fstream
,但我意識到無法在獨佔模式下打開它。由於有很多線程我想允許多個讀取,並且當在寫入模式下打開文件時,我想以獨佔模式打開文件?
做什麼是最好的方法?我認爲Boost
提供了一些功能。還有其他的可能嗎?我也想看一個簡單的例子。如果在C++中不容易/很好,我也可以用C語言編寫。如何以獨佔模式在C++中打開文件
我正在使用Windows。
我正在用C++實現一些文件系統。到目前爲止,我使用的是fstream
,但我意識到無法在獨佔模式下打開它。由於有很多線程我想允許多個讀取,並且當在寫入模式下打開文件時,我想以獨佔模式打開文件?
做什麼是最好的方法?我認爲Boost
提供了一些功能。還有其他的可能嗎?我也想看一個簡單的例子。如果在C++中不容易/很好,我也可以用C語言編寫。如何以獨佔模式在C++中打開文件
我正在使用Windows。
那麼你可以手動防止你打開一個文件,如果它已經被寫入模式打開。只需在內部跟蹤您在寫入模式下打開的文件。
也許你可以散列文件名,並在打開寫入權限後將其存儲在表中。這將允許快速查找以查看文件是否已被打開。
我不確定它是否是最好的主意,因爲我將不得不保留所有打開的文件。 (請注意,如果一個fileA在讀取模式下打開,並且某人想要在寫入模式下打開它,則需要等到讀取模式完成)。 – rank1 2013-04-22 07:38:55
在許多操作系統上,這根本不可能,所以C++ 不支持它。你必須寫自己的streambuf
。 如果您擔心的唯一平臺是Windows,則您可以使用 開放的獨佔模式。 更可能的,但是,你可能需要使用某種形式的文件 鎖定,這是更準確,可在大部分的,如果不是 所有平臺(但不包括可移植—您需要使用Windows,fcntl
下LockFileEx
下Unix的)。
在Posix下,您還可以使用pthread_rwlock
。 Butenhof 給出了這樣的一個實現採用經典的互斥和 條件變量,這是目前在C++ 11,所以你可以 真正實現便攜版(提供的所有 讀者和作家都在同一個進程—了POSIX 請求將跨越進程邊界工作,但這不是針對C++線程原語的 )。
如何以及爲什麼要編寫自己的streambuf?我認爲這會更容易使用這個Windows API,如http://msdn.microsoft.com/en-us/library/windows/desktop/aa365204(v=vs.85).aspx – rank1 2013-04-22 10:12:44
@ SebastianCygert The Windows API需要輸出一個'char'緩衝區; 'ostream'接口處理格式和轉換爲字符串。 'streambuf'類是兩者之間的橋樑。 – 2013-04-22 11:11:20
如果你的應用程序只能在Windows上運行,那麼win32 API函數「CreateFile()」是你的選擇。例如:HANDLE hFile = :: CreateFileW(lpszFileFullPathName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);
例如:HANDLE hFile = :: CreateFileW(lpszFileFullPathName,GENERIC_WRITE,\t FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL); – skyfree 2013-04-22 13:24:38
你想編輯你的答案並在那裏添加你的例子。 – 2016-06-01 03:05:01
您可以重命名該文件,使用新名稱進行更新,然後重新命名。我已經做到了,但有點沉重。
如果你打算使用boost,那麼我建議你使用file_lock類。這意味着你想保留你打開/關閉的文件的文件名,因爲fstream不會爲你做這些。
他們有兩種模式lock()
,你可以使用書面形式(在時間,即只有一個這樣的鎖,共享鎖也可以防止這種鎖)和lock_sharable()
,您可以使用閱讀(即任意數量的線程能夠取得這樣的一把鎖)。
請注意,您會發現以這種方式管理讀寫操作最終會變得很複雜。也就是說,如果總是有人閱讀,那麼可共享的鎖定可能永遠不會被釋放。在這種情況下,排他鎖永遠不會有機會...
// add the lock in your class
#include <boost/interprocess/sync/file_lock.hpp>
class my_files
{
...
private:
...
boost::file_lock m_lock;
};
現在當你想要訪問一個文件時,你可以用某種方式鎖定它。如果線程負責執行此操作,則可以爲用戶添加功能以訪問該鎖。如果你讀的執行和寫入功能my_files是主管,你想獲得該鎖基於堆棧的對象,並解鎖你(RAII):
class safe_exclusive_lock
{
public:
safe_exclusive_lock(file_lock & lock)
: m_lock_ref(lock)
{
m_lock_ref.lock();
}
~safe_exclusive_lock()
{
m_lock_ref.unlock();
}
private:
file_lock & m_lock_ref;
};
現在可以安全地鎖定該文件(即你
ssize_t my_files::read(char *buf, size_t len)
{
safe_exclusive_lock guard(m_lock);
...your read code here...
return len;
} // <- here we get the unlock()
ssize_t my_files::write(char const *buf, size_t len)
{
safe_exclusive_lock guard(m_lock);
...your write code here...
return len;
} // <- here we get the unlock()
的file_lock使用文件,所以你會希望有每次創建file_lock已經創建了fstream的文件:鎖,做的事情,可能會拋出,你總是退出當前的{} - 塊)之前解鎖。如果fstream的文件可能無法在構造函數來創建的,你可能會想改造m_lock變量的唯一指針:
private:
std::unique_ptr<file_lock> m_lock;
當你引用它,你現在需要一個星號:
safe_exclusive_lock guard(*m_lock);
請注意,爲了安全,你應該檢查一下指針是否確實分配,如果沒有定義,這意味着該文件尚未打開,所以我建議你扔:
if(m_lock)
{
safe_exclusive_lock guard(*m_lock);
...do work here...
}
else
{
throw file_not_open();
}
// here the lock was released so you cannot touch the file anymore
在日E打開,創建鎖:
bool open(std::string const & filename)
{
m_stream.open(...);
...make sure it worked...
m_lock.reset(new file_lock(filename));
// TODO: you may want a try/catch around the m_lock and
// close the m_stream if it fails or use a local
// variable and swap() on success...
return true;
}
而且不要忘記釋放鎖對象在接近:
void close()
{
m_lock.reset();
}
相關[boost interprocess_lock不適用於多個進程](http://stackoverflow.com/questions/6697704/boost-interprocess-file-lock-does-not-work-with-multiple-processes) – 2016-06-01 03:31:56
這種低層次的東西最好是用C實現,用盡可能少的開銷可能... – 2013-04-22 06:51:17
@ bash.d胡說,你爲什麼這麼想? C++的重點是提供免費的抽象。我曾把你當作知道這件事的人盯上。 – 2013-04-22 09:08:53
@KonradRudolph我不瞭解你,但我不知道用C++實現的許多文件系統... – 2013-04-22 09:10:12