内存映射文件、托管映射文件和偏移指针

Memory Mapped Files, Managed Mapped File and Offset Pointer

本文关键字:映射 文件 指针 内存      更新时间:2023-10-16

我对Boost Library(用于windows)的术语有点困惑。我想做的只是;在磁盘上创建一个文件(一个大于50 GB的大文件),分别为写入和读取操作进行一些映射。

例如,用于写入的第一映射1gb部分&之后将其刷新到硬盘驱动器,获取一个新的部分,依此类推,而阅读器应用程序映射文件的不同部分,并在不更改任何内容的情况下进行读取(无需编辑)。

我正在阅读boost的文档(1.47.0版本,因为我们允许使用这个版本),我不知道什么时候应该使用内存映射文件方法,例如:file_mapping、managed_region和托管映射文件basic_managed_Mapped_file和Offset_Ptr。

有人能告诉我内存映射文件和托管映射文件之间的区别吗?它们的用途是什么?

如果可能的话,一些示例代码将对这些和Offset_ptr进行高度概括。

真的很感谢。。。

您可以使用managed_mapped_file从内存映射文件透明地进行分配。

这意味着,出于所有实际目的,您通常不需要对内存区域进行双重划分。无论如何,它都是虚拟内存,所以分页负责在所需的时间加载正确的位。

显然,如果存在大量碎片或访问"跳跃",那么分页可能会成为性能瓶颈。在这种情况下,可以考虑细分为多个池并从中进行分配。)_

编辑刚刚注意到Boost IPC在隔离存储节点分配器和自适应池节点分配器下支持此功能。这里还有关于这些存储池的实现的说明。

这里有一个简单的起点,创建一个50Gb的文件并在其中填充一些数据:

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>
#include <boost/interprocess/managed_mapped_file.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
namespace bip = boost::interprocess;
using mutex_type    = bip::named_mutex;
struct X
{
char buf[100];
double rate;
uint32_t samples[1024];
};
template <typename T> using shared_alloc  = bip::allocator<T,bip::managed_mapped_file::segment_manager>;
template <typename T> using shared_vector = boost::container::vector<T, shared_alloc<T> >;
template <typename K, typename V, typename P = std::pair<K,V>, typename Cmp = std::less<K> >
using shared_map    = boost::container::flat_map<K, V, Cmp, shared_alloc<P> >;
using shared_string = bip::basic_string<char,std::char_traits<char>,shared_alloc<char> >;
using dataset_t     = shared_map<shared_string, shared_vector<X> >;
struct mutex_remove
{
mutex_remove() { mutex_type::remove("7FD6D7E8-320B-11DC-82CF-39598D556B0E"); }
~mutex_remove(){ mutex_type::remove("7FD6D7E8-320B-11DC-82CF-39598D556B0E"); }
} remover;
static mutex_type mutex(bip::open_or_create,"7FD6D7E8-320B-11DC-82CF-39598D556B0E");
static dataset_t& shared_instance()
{
bip::scoped_lock<mutex_type> lock(mutex);
static bip::managed_mapped_file seg(bip::open_or_create,"./demo.db", 50ul<<30); // "50Gb ought to be enough for anyone"
static dataset_t* _instance = seg.find_or_construct<dataset_t>
("DATA")
(
std::less<shared_string>(), 
dataset_t::allocator_type(seg.get_segment_manager())
);
static auto capacity = seg.get_free_memory();
std::cerr << "Free space: " << (capacity>>30) << "gn";
return *_instance;
}
int main()
{
auto& db = shared_instance();
bip::scoped_lock<mutex_type> lock(mutex);
auto alloc = db.get_allocator().get_segment_manager();
std::cout << db.size() << 'n';
for (int i = 0; i < 1000; ++i)
{
std::string key_ = "item" + std::to_string(i);
shared_string key(alloc);
key.assign(key_.begin(), key_.end());
auto value = shared_vector<X>(alloc);
value.resize(size_t(rand()%(1ul<<9)));
auto entry = std::make_pair(key, value);
db.insert(std::make_pair(key, value));
}
}

请注意,它编写了一个50G的稀疏文件。承诺的实际大小取决于其中的一点随机性。我的跑步成绩大约为1.1G:

$ du -shc --apparent-size demo.db 
50G demo.db
$ du -shc demo.db 
1,1G    demo.db

希望这能帮助