2017-08-08 79 views
4

我需要在重新啓動時持續保留uint64_t標記。使用內存映射文件進行持久化 - 是否需要volatile?

要做到這一點,我使用boost::interprocess::mapped_region內存映射,我在同一個進程創建一個文件:

bip::file_mapping file(filename.c_str(), bip::read_write); 
auto region = std::make_unique<bip::mapped_region>(file, bip::read_write); 

我再投地址到我的uint64_t類型現在

using Tag = uint64_t; 
Tag& curr_ = *reinterpret_cast<Tag*>(region->get_address()); 

我可以後增加標籤,獲得「下一個標籤」,並且結果在重新啓動後持續存在

Tag next = curr_++; 

請注意,這個文件是寫入只讀通過這個過程。它的目的純粹是提供持久性。

問:

是我Tag& curr_,是非易失性的,並且執行I/O的內存映射區域,不確定的行爲?

爲了正確,我的代碼是否需要volatile關鍵字?

全部工作如下例子:

#include <boost/interprocess/mapped_region.hpp> 
#include <boost/interprocess/file_mapping.hpp> 
#include <sys/stat.h> 
#include <fstream> 
#include <cstdint> 
#include <memory> 
#include <iostream> 

namespace bip = boost::interprocess; 

using Tag = uint64_t; 

Tag& map_tag(const std::string& filename, 
      std::unique_ptr<bip::mapped_region>& region) 
{ 
    struct stat buffer; 
    if (stat(filename.c_str(), &buffer) != 0) 
    { 
     std::filebuf fbuf; 
     fbuf.open(filename.c_str(), std::ios_base::in | 
            std::ios_base::out | 
            std::ios_base::trunc | 
            std::ios_base::binary); 

     Tag tag = 1; 
     fbuf.sputn((char*)&tag, sizeof(Tag)); 
    } 

    bip::file_mapping file(filename.c_str(), bip::read_write); 

    // map the whole file with read-write permissions in this process 
    region = std::make_unique<bip::mapped_region>(file, bip::read_write); 

    return *reinterpret_cast<Tag*>(region->get_address()); 
} 

class TagBroker 
{ 
public: 
    TagBroker(const std::string& filename) 
     : curr_(map_tag(filename, region_)) 
    {} 

    Tag next() 
    { 
     return curr_++; 
    } 

private: 
    std::unique_ptr<bip::mapped_region> region_; 
    Tag& curr_; 
}; 

int main() 
{ 
    TagBroker broker("/tmp/tags.bin"); 

    Tag tag = broker.next(); 

    std::cout << tag << '\n'; 
    return 0; 
} 

輸出:

在整個運行中,持久性被保持。

$ ./a.out 
1 
$ ./a.out 
2 
$ ./a.out 
3 
$ ./a.out 
4 

我不知道這是否是正確的,因爲我的過程是唯一一個從讀/寫Tag& curr_,或者如果它只是偶然的工作,並且,事實上,不確定的行爲。

+0

我如果您的程序以外的其他程序正在寫入該文件,則認爲易失性只是必要的? – AndyG

+0

@AndyG,我也是這樣 - 但由於I/O調度器將處理實際的讀/寫磁盤,這是否被認爲是另一個過程?我的理解不是,並且volatile *不是必需的,但我不是100%確定的,因此,這個問題 –

回答

2

在這種情況下,沒有。

在引擎蓋下,Boost的interprocess/mapped_region.hpp使用的是mmap,它會返回一個指向你內存映射區域的指針。

如果您懷疑另一個進程(或硬件)可能正在寫入您的文件,則只需使用volatile

(這將是最基本的同步,你應該提供的,因爲volatile強制從每個存取存儲器讀取。如果你有在過程控制,你可以嘗試像一個信號更先進的同步。)

+0

因此,對於這個特定的用例,這是我的過程**只有一個寫入文件** ,那麼不需要'volatile',也不需要更高級的同步,比如信號量等。 –

+0

對不起,先生 – AndyG

+0

感謝您的支持! –

相關問題