【问题标题】:shm_open and mmap with stl vector带有 stl 向量的 shm_open 和 mmap
【发布时间】:2012-09-18 04:56:15
【问题描述】:

我了解到 stl 向量不适用于 SYS V 共享内存。但是,如果我使用 POSIX shm_open 然后使用 NULL 的 mmap (mmap(NULL, LARGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0) 并给出比包含我的向量的对象大得多的大小,并且在映射后添加附加项目到向量,除了超过 LARGE_SIZE 空间之外还有其他问题吗?其他相关问题:在最近的 SUSE linux 上是否保证在不相关的进程中映射到相同的起始地址(使用上述语法)时,我的对象将被直接映射并且不执行(系统)复制来实现进程中的更改值(例如在 mmap-ed 时正常打开和正常文件会发生什么)? 谢谢!

编辑: 那么这样对吗?:

void* mem = allocate_memory_with_mmap(); // say from a shared region
MyType* ptr = new ( mem ) MyType( args );
ptr.~MyType() //is this really needed?

现在处于一个不相关的过程中:

MyType* myptr = (MyType*)fetch_address_from_mmap(...)
myptr->printHelloWorld();
myptr->myvalue = 1; //writes to shared memory
myptr.~MyType() //is this really needed?

现在如果我想释放内存

munmap(address...) //but this done only once, when none of the processes use it any more

【问题讨论】:

    标签: memory vector mapping posix shared


    【解决方案1】:

    您忽略了一个事实,即 STL 向量通常只是 (mem pointer, mem size, element count) 的元组,其中包含对象的实际内存是从 allocator 模板参数接收的。

    std::vector 的实例放在共享内存中没有任何意义。您可能想查看 boost::interprocess 库。

    编辑 0:

    内存分配和对象构造是两个不同的阶段,尽管组合在一个语句中,如下所示(除非为 MyType 重新定义运算符 new):

    // allocates from process heap and constructs
    MyType* ptr = new MyType( args );
    

    您可以使用placement new 拆分这两个阶段:

    void* mem = allocate_memory_somehow(); // say from a shared region
    MyType* ptr = new ( mem ) MyType( args );
    

    虽然现在你必须显式调用析构函数并释放内存:

    ptr->~MyType();
    release_memory_back_to_where_it_came_from( ptr );
    

    这本质上就是在 C++ 中如何在共享内存中构造对象。请注意,存储指针的类型不适合共享内存,因为一个进程内存空间中的任何指针在另一个进程内存空间中都没有任何意义。请改用明确的尺寸和偏移量。

    希望这会有所帮助。

    【讨论】:

    • 也许我缺少一些基本的理解......你能告诉我,如果我通过 mmap (MyPointer* a) 绑定一个指针。然后说 a = new MyPointer()。将在哪里分配对象。在共享内存还是进程空间?如果在进程空间中,那么如果其他进程尝试使用它会发生什么?
    • 哦,我明白了,所以“普通旧”new 会将对象放在进程私有堆中而不是将其复制到共享内存中?但是为什么我需要以这种方式删除它?我不能通过强制转换(MyType*)给 mem 一个类型,然后在 mem 上使用 delete 运算符(delete mem)吗?
    • 好的,我认为删除操作符没有太大意义。但是你说它从哪里来是什么意思?关于发布,我将不得不使用 munmap(它将 POSIX 对象从 shm 中释放出来)。为什么我需要把它放回某个地方?另外我希望我可以将 mem 转换为 MyType 类,否则我怎么能在不相关的过程中使用它的非指针成员变量和成员函数。手动调用析构函数不是很清楚,为什么这么重要。
    • 基本上,您需要一个“主”进程来创建共享内存并在其中填充数据结构(在这里您可以使用上面的构造函数,或者为了简单起见只做 POD),然后“从”进程将映射该内存并转换为适当的类型。
    猜你喜欢
    • 1970-01-01
    • 2016-04-30
    • 2013-12-28
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2012-03-05
    • 1970-01-01
    相关资源
    最近更新 更多