当一个进程截断由boost进程库创建的共享内存时,进程需要重新映射

时间:2018-01-07 16:36:33

标签: c++ boost shared-memory interprocess

Boost进程间共享内存需要重映射,当其中一个进程截断共享内存以获得动态增长的大小时,也会重新获取地址。代码如下,在实际情况下,消费者mapping可以了解生产者trunc每次创建的新内存界限。但是,当trunc创建更大的内存时,当输入更大的偏移量到mapping时,映射会崩溃。

./trunc 10
./mapping
input 9, output is 9.
./trunc 10000, 
input 9999 to mapping process, then segmentation fault.

trunc.cpp

#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>

namespace bi = boost::interprocess;

int main(int argc, char* argv[]) {
    bi::shared_memory_object shm(bi::open_or_create, "testshm", bi::read_write);
    shm.truncate(sizeof(int) * std::atoi(argv[1]));
    bi::mapped_region reg(shm, bi::read_write, 0);
    int* p = (int*)reg.get_address();
    for(std::size_t i = 0; i < std::atoi(argv[1]); ++i)
        p[i] = i;

    return 0;
}

mapping.cpp

#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>

namespace bi = boost::interprocess;

int main(int argc, char* argv[]) {

    bi::shared_memory_object shm(bi::open_only, "testshm", bi::read_only);
    bi::mapped_region reg(shm, bi::read_only, 0);
    int* p = (int*)reg.get_address();
    do {
        std::cout << "Please input offset:" << std::endl;
        int offset;
        std::cin >> offset;
        std::cout << "Integer @" << offset << " is " << p[offset] << std::endl;


    } while(true);
    return 0;
}

1 个答案:

答案 0 :(得分:1)

在我的系统上不会发生这种情况。

可悲的是,我无法向你展示Coliru(因为不支持共享内存),但您可以使用以下代码重新测试:

#include <iostream>
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>

namespace bi = boost::interprocess;

static char const* const SHM_NAME = "sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4";

int main(int argc, char** argv) {
    if (argc>1) {
        bi::shared_memory_object shm(bi::open_or_create, SHM_NAME, bi::read_write);

        shm.truncate(sizeof(int) * std::atoi(argv[1]));
        bi::mapped_region reg(shm, bi::read_write);

        int* p = reinterpret_cast<int*>(reg.get_address());

        for(int i = 0; i < std::atoi(argv[1]); ++i)
            p[i] = i;

        std::cout << "Truncated and filled to " << reg.get_size() << "\n";
    } else {
        bi::shared_memory_object shm(bi::open_only, SHM_NAME, bi::read_only);
        bi::mapped_region reg(shm, bi::read_only, 0);

        size_t N = reg.get_size() / 4;
        int const* p = reinterpret_cast<int const*>(reg.get_address());

        size_t index;
        while (std::cout << "Please input index: " && std::cin >> index) {
            if (index < N)
                std::cout << "Integer @" << index << " is " << p[index] << "\n";
            else
                std::cout << "Index " << index << " out of bounds [0.." << N << ")\n";
        }
        std::cout << "Bye\n";
    }
}

它主要改变了一些小事:

  • 名称
  • 检查大小是否已截断/在建立索引之前
  • 拼写reinterpret_cast
  • 常量-正确性
  • truncmapping合并为一个文件

我用以下方法测试:

测试案例1:截断10

./sotest 10
xxd /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4 | tail -5
ls -ltra /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
./sotest <<< "0 1 2 3 999 9999 10000"

输出:

Truncated and filled to 40
00000000: 0000 0000 0100 0000 0200 0000 0300 0000  ................
00000010: 0400 0000 0500 0000 0600 0000 0700 0000  ................
00000020: 0800 0000 0900 0000                      ........
-rw-r--r-- 1 sehe sehe 40 jan  7 21:08 /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
Please input index: Integer @0 is 0
Please input index: Integer @1 is 1
Please input index: Integer @2 is 2
Please input index: Integer @3 is 3
Please input index: Index 999 out of bounds [0..10)
Please input index: Index 9999 out of bounds [0..10)
Please input index: Index 10000 out of bounds [0..10)
Please input index: Bye

测试用例1:截断10000

sotest 10000
xxd /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4 | tail -5
ls -ltra /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
./sotest <<< "0 1 2 3 999 9999 10000"

输出:

Truncated and filled to 40000
00009bf0: fc26 0000 fd26 0000 fe26 0000 ff26 0000  .&...&...&...&..
00009c00: 0027 0000 0127 0000 0227 0000 0327 0000  .'...'...'...'..
00009c10: 0427 0000 0527 0000 0627 0000 0727 0000  .'...'...'...'..
00009c20: 0827 0000 0927 0000 0a27 0000 0b27 0000  .'...'...'...'..
00009c30: 0c27 0000 0d27 0000 0e27 0000 0f27 0000  .'...'...'...'..
-rw-r--r-- 1 sehe sehe 40000 jan  7 21:08 /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
Please input index: Integer @0 is 0
Please input index: Integer @1 is 1
Please input index: Integer @2 is 2
Please input index: Integer @3 is 3
Please input index: Integer @999 is 999
Please input index: Integer @9999 is 9999
Please input index: Index 10000 out of bounds [0..10000)
Please input index: Bye

测试用例1:截断10001

sotest 10001
xxd /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4 | tail -5
ls -ltra /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
./sotest <<< "0 1 2 3 999 9999 10000"

输出:

Truncated and filled to 40004
00009c00: 0027 0000 0127 0000 0227 0000 0327 0000  .'...'...'...'..
00009c10: 0427 0000 0527 0000 0627 0000 0727 0000  .'...'...'...'..
00009c20: 0827 0000 0927 0000 0a27 0000 0b27 0000  .'...'...'...'..
00009c30: 0c27 0000 0d27 0000 0e27 0000 0f27 0000  .'...'...'...'..
00009c40: 1027 0000                                .'..
-rw-r--r-- 1 sehe sehe 40004 jan  7 21:08 /dev/shm/sotest-5b4f4154-0c7a-48f4-9be6-33b99094cea4
Please input index: Integer @0 is 0
Please input index: Integer @1 is 1
Please input index: Integer @2 is 2
Please input index: Integer @3 is 3
Please input index: Integer @999 is 999
Please input index: Integer @9999 is 9999
Please input index: Integer @10000 is 10000
Please input index: Bye

如果这会对您的系统产生不同的结果,请告诉我们。另外,报告 平台详细信息/版本使用该案例。