调整POSIX共享内存的大小。一个工作的例子

时间:2016-11-03 10:15:05

标签: c linux shared-memory mmap

我在POSIX模型中有两个不同应用程序之间的共享动态数组。我希望有能力改变它的大小而不复制。不幸的是,我无法找到正确的解决方案来增加和减少C语言中的POSIX共享内存。在网络上,我发现很多文档都有不好的解释和可怜的例子。我设法找到了一些有趣的话题,但所有这些话都不适合我:

  1. "Linux System Programming" - "Mapping Files into Memory" Part: "Resizing a Mapping" - 这里没有调整SHM大小的实例。

  2. How do I implement dynamic shared memory resizing? - 仅供说明。没有例子。

  3. mremap function failed to allocate new memory - 最喜欢的答案有误。

  4. Fast resize of a mmap file

  5. Characteristics of mremap function in Linux

  6. mremap function failed to allocate new memory

  7. c/linux - ftruncate and POSIX Shared Memory Segments - rszshm根本不使用mremap()。它复制内存。最坏的方式。

  8. 我已经开发了一个例子,因为我理解了文档。不幸的是它无法正常工作。请给我一个建议,我错了。请非常友好地给我一个有效的例子。

    在文档中我发现我必须在mremap()之前使用ftruncate(),但我找不到使用它们的正确语法。此外,mremap()适用于对齐的内存页面。在这种情况下如何正确增加共享内存?

    /* main.c */
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <errno.h>
    
    int main(void)
    {
        size_t size_of_mem = 1024;
        int fd = shm_open("/myregion", O_CREAT | O_RDWR,
                          S_IRWXO | S_IRUSR | S_IWUSR);
        if (fd == -1)
        {
            perror("Error in shm_open");
            return EXIT_FAILURE;
        }
    
        if (ftruncate(fd, size_of_mem) == -1)
        {
            perror("Error in ftruncate");
            return EXIT_FAILURE;
        }
    
        void *shm_address = mmap(0, size_of_mem,
                                 PROT_READ | PROT_WRITE | PROT_EXEC,
                                 MAP_SHARED, fd, 0);
        if (shm_address == MAP_FAILED)
        {
            perror("Error mmapping the file");
            return EXIT_FAILURE;
        }
    
        /* Increase shard memory */
        for (size_t i=0; i<1024; ++i){
    
            /* Does 8 align memory page? */
            size_t new_size_of_mem = 1024+(8*i);
    
            if (ftruncate(fd, new_size_of_mem) == -1)
            {
                perror("Error in ftruncate");
                return EXIT_FAILURE;
            }
    
            /*
               mremap() works with  aligned memory pages.
               How to properly increase shared memory in this case?
            */
            void *temp = mremap(shm_address, size_of_mem, new_size_of_mem, MREMAP_MAYMOVE);
            if(temp == (void*)-1)
            {
                perror("Error on mremap()");
                return EXIT_FAILURE;
            }
    
            size_of_mem = new_size_of_mem;
    
        }
    
        return 0;
    }
    

    构建

    $ gcc -g -O0 -ggdb -pipe -Wall -Wextra -Wpedantic -Wshadow -march=native -std=c11 -o ./main ./main.c -lrt
    

    执行命令

    $ ./main
    Error on mremap(): Bad address
    

1 个答案:

答案 0 :(得分:5)

您正在丢失分配给temp的新分配/重新映射内存的地址。

这意味着,自for循环的第二个循环开始,您正在移动已经移动的内存。

检查mremap返回值后,您可以将新地址重新分配给shm_address指针。

void *temp = mremap(shm_address, size_of_mem, new_size_of_mem, MREMAP_MAYMOVE);
if(temp == (void*)-1)
{
    perror("Error on mremap()");
    return EXIT_FAILURE;
}

shm_address = temp;