使用mremap调整mmap共享内存的大小失败

时间:2019-06-05 23:37:45

标签: memory fork mmap

我正在一个项目中,我需要在使用fork()API创建的进程之间共享大量std :: pair。程序开始时未知数组的大小。稍后,父进程将与子进程进行通信,以确定数组的大小。然后,它将通过调用mremap()API来调整共享内存空间的大小。到目前为止,我没有使用mmap和mremap的运气。 在我看来,当新大小变得大于4096字节(系统的页面大小?)时,mremap()失败。

我创建了一个小例子来帮助我更好地理解问题。此代码,使用mmap()创建共享内存,然后在多个步骤中使用mremap增加其大小。在此示例中,只有一个过程。 我还将请求的共享内存的大小四舍五入为4096字节。

#include <iostream>
#include <sys/types.h> /* pid_t */
#include <sys/wait.h>
#include <unistd.h>  /* _exit, fork */
#include <stdlib.h>  /* exit */
#include <errno.h>   /* errno */
#include <time.h>       /* time */
#include <sys/mman.h>
#include <vector>
#include <map>
#include <string.h>
#include  <sys/ipc.h>
#include  <sys/shm.h>
#define page_size 4096
#define def_size  32

void write_shmem (long *shm_ptr, long npt)
{
    for (long pt = 0; pt < npt ; ++pt)
    {
        shm_ptr[pt] = 77;
        //std::cout << "shm_ptr[" << pt << "] = " <<  shm_ptr[pt] << "\n";
    }
}

long read_shmem (long *shm_ptr, long npt)
{
    long bad_indx = -1;
    for (long pt = 0; pt < npt ; ++pt)
    {
        if (shm_ptr[pt] != 77)
        {
            bad_indx = pt;
            break;
        }
    }
    return bad_indx;
}

int main ()
{

    void * add;
    long *shm_arcs;
    long padding = 0;
    long init_shmem_size = sizeof (long) *def_size;
    long resid = init_shmem_size % page_size;
    if (resid!=0) padding = page_size  - (init_shmem_size % page_size);
    //std::cout << " requested " << init_shmem_size << " bytes, translated to " << padding+init_shmem_size << "\n";
    init_shmem_size +=padding;
    add = mmap(NULL, init_shmem_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); // initial size is set to npt.
    if (add == MAP_FAILED)
    {
        std::cout << "Mapped failed at parent \n";
        exit(-1);
    }
    shm_arcs = (long *) add;
    write_shmem (shm_arcs, def_size);
    long bd = read_shmem (shm_arcs, def_size);

    if (bd!=-1)
    {
        std::cout << "Shmem test failed at " << bd << "\n";
        exit(-1);
    }

    std::cout<<"Parent: shared memory is created and verified at address " << shm_arcs <<" data size: " << init_shmem_size << ".\n ";


    long *shm_new = shm_arcs;
    long nsize = def_size;
    for (int i = 0; i< 1000; i ++)
    {
        nsize += def_size;
        long bsize = nsize*sizeof(long);
        if ((bsize % page_size)!=0) padding = page_size  - (bsize % page_size);
        else padding = 0;
        //std::cout << nsize << " elements requested " << bsize << " bytes, translated to " << padding+bsize << "\n";
        bsize+=padding;
        add = mremap(shm_new, init_shmem_size, bsize , MREMAP_MAYMOVE);
        if (add != shm_new)
        {
            std::cout << "Old mem unmapped ---------------";
            munmap(shm_new, init_shmem_size);
        }
        if (add == MAP_FAILED)
        {
            std::cout << "Mapped failed at parent  at " << i << "\n";
            exit(-1);
        }
        shm_new = (long *) add;

        write_shmem (shm_new, nsize);
        long bd = read_shmem (shm_arcs, nsize);
        if (bd!=-1)
        {
            std::cout << "Shmem test failed at " << bd << "\n";
            exit(-1);
        }

        std::cout<< i << " - Parent: shared memory is created and verified at address " << shm_new <<" with " << nsize << " elements, data size : " << bsize <<  ".\n ";

        init_shmem_size = bsize;
    }
    return 0;
}

这是代码的输出:     父级:在地址0x7f00ae91b000处创建并验证了共享内存,数据大小:4096。

0 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 64 elements, data size : 4096.
 1 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 96 elements, data size : 4096.
 2 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 128 elements, data size : 4096.
 3 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 160 elements, data size : 4096.
 4 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 192 elements, data size : 4096.
 5 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 224 elements, data size : 4096.
 6 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 256 elements, data size : 4096.
 7 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 288 elements, data size : 4096.
 8 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 320 elements, data size : 4096.
 9 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 352 elements, data size : 4096.
10 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 384 elements, data size : 4096.
11 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 416 elements, data size : 4096.
12 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 448 elements, data size : 4096.
13 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 480 elements, data size : 4096.
14 - Parent: shared memory is created and verified at address 0x7f00ae91b000 with 512 elements, data size : 4096.
Bus error

我正在Linux上运行它。 我在这里做错了什么?如果这不是执行此操作的最佳方法,那么不胜感激,您能指出更好的方法吗?

谢谢

1 个答案:

答案 0 :(得分:0)

您不应该尝试取消映射mremap之后的旧地址,因为旧地址已被取消映射,并且可能与新地址范围重叠。您的“旧内存未映射”消息将不会被打印,因为cout已被缓冲,并且该进程在刷新该缓冲之前就死了。