Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用内存映射文件进行持久化-是否需要volatile?_C++_Volatile_Memory Mapped Files_Boost Interprocess - Fatal编程技术网

C++ 使用内存映射文件进行持久化-是否需要volatile?

C++ 使用内存映射文件进行持久化-是否需要volatile?,c++,volatile,memory-mapped-files,boost-interprocess,C++,Volatile,Memory Mapped Files,Boost Interprocess,我需要一个uint64\u t标记在重启期间持久化 为了实现这一点,我正在使用boost::进程间::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\u t
标记在重启期间持久化

为了实现这一点,我正在使用
boost::进程间::mapped_region
对我在同一进程中创建的文件进行内存映射:

bip::file_mapping file(filename.c_str(), bip::read_write);
auto region = std::make_unique<bip::mapped_region>(file, bip::read_write);
现在我可以发布增量标记,获得“下一个标记”,并且结果会在重新启动时持久化

Tag next = curr_++;
请注意,此文件仅通过此过程写入,并从读取。它的目的纯粹是提供持久性

问题:

#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;
}
我的
标记和电流是非易失性的,并且对内存映射区域执行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;
}
我不知道这是否正确,因为我的过程是唯一一个读取/写入
标记和电流的过程,或者它只是偶然工作,实际上是未定义的行为。

在这种情况下,没有

在引擎盖下,Boost的进程间/映射_region.hpp正在使用
mmap
,它将返回指向内存映射区域的指针

如果怀疑其他进程(或硬件)可能正在写入文件,则只需使用
volatile


(这将是您应该提供的最基本的同步,因为
volatile
在每次访问时强制从内存读取。如果您可以控制进程,您可以尝试更高级的同步,如信号灯。)

我认为volatile只有在程序以外的其他程序正在写入该文件时才有必要?@AndyG我也这么认为-但是由于I/O调度程序将处理从磁盘的实际读取/写入,这是否被视为另一个过程?我的理解是不需要的,也不需要volatile,但我不是100%确定的,因此这个问题对于这个特定的用例来说,我的过程是唯一一个写入文件的过程,那么
volatile
就不需要了,也不需要任何更高级的同步,比如信号灯等?是的,先生
$ ./a.out
1
$ ./a.out
2
$ ./a.out
3
$ ./a.out
4