2013-04-22 30 views
3

我正在用C++實現一些文件系統。到目前爲止,我使用的是fstream,但我意識到無法在獨佔模式下打開它。由於有很多線程我想允許多個讀取,並且當在寫入模式下打開文件時,我想以獨佔模式打開文件?
做什麼是最好的方法?我認爲Boost提供了一些功能。還有其他的可能嗎?我也想看一個簡單的例子。如果在C++中不容易/很好,我也可以用C語言編寫。如何以獨佔模式在C++中打開文件

我正在使用Windows。

+1

這種低層次的東西最好是用C實現,用盡可能少的開銷可能... – 2013-04-22 06:51:17

+1

@ bash.d胡說,你爲什麼這麼想? C++的重點是提供免費的抽象。我曾把你當作知道這件事的人盯上。 – 2013-04-22 09:08:53

+1

@KonradRudolph我不瞭解你,但我不知道用C++實現的許多文件系統... – 2013-04-22 09:10:12

回答

0

那麼你可以手動防止你打開一個文件,如果它已經被寫入模式打開。只需在內部跟蹤您在寫入模式下打開的文件。

也許你可以散列文件名,並在打開寫入權限後將其存儲在表中。這將允許快速查找以查看文件是否已被打開。

+0

我不確定它是否是最好的主意,因爲我將不得不保留所有打開的文件。 (請注意,如果一個fileA在讀取模式下打開,並且某人想要在寫入模式下打開它,則需要等到讀取模式完成)。 – rank1 2013-04-22 07:38:55

2

在許多操作系統上,這根本不可能,所以C++ 不支持它。你必須寫自己的streambuf。 如果您擔心的唯一平臺是Windows,則您可以使用 開放的獨佔模式。 更可能的,但是,你可能需要使用某種形式的文件 鎖定,這是更準確,可在大部分的,如果不是 所有平臺(但不包括可移植—您需要使用Windows,fcntlLockFileEx 下Unix的)。

在Posix下,您還可以使用pthread_rwlock。 Butenhof 給出了這樣的一個實現採用經典的互斥和 條件變量,這是目前在C++ 11,所以你可以 真正實現便攜版(提供的所有 讀者和作家都在同一個進程—了POSIX 請求將跨越進程邊界工作,但這不是針對C++線程原語的 )。

+0

如何以及爲什麼要編寫自己的streambuf?我認爲這會更容易使用這個Windows API,如http://msdn.microsoft.com/en-us/library/windows/desktop/aa365204(v=vs.85).aspx – rank1 2013-04-22 10:12:44

+0

@ SebastianCygert The Windows API需要輸出一個'char'緩衝區; 'ostream'接口處理格式和轉換爲字符串。 'streambuf'類是兩者之間的橋樑。 – 2013-04-22 11:11:20

1

如果你的應用程序只能在Windows上運行,那麼win32 API函數「CreateFile()」是你的選擇。例如:HANDLE hFile = :: CreateFileW(lpszFileFullPathName,GENERIC_WRITE,FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL);

+0

例如:HANDLE hFile = :: CreateFileW(lpszFileFullPathName,GENERIC_WRITE,\t FILE_SHARE_READ,NULL,OPEN_EXISTING,NULL,NULL); – skyfree 2013-04-22 13:24:38

+0

你想編輯你的答案並在那裏添加你的例子。 – 2016-06-01 03:05:01

0

您可以重命名該文件,使用新名稱進行更新,然後重新命名。我已經做到了,但有點沉重。

0

如果你打算使用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(); 
} 
+0

相關[boost interprocess_lock不適用於多個進程](http://stackoverflow.com/questions/6697704/boost-interprocess-file-lock-does-not-work-with-multiple-processes) – 2016-06-01 03:31:56