Den*_*.R. 10 c linux mmap shared-memory
我在POSIX模型中有两个不同应用程序之间的共享动态数组.我希望有能力改变它的大小而不复制.不幸的是我无法找到正确的解决方案来增加和减少C语言中的POSIX共享内存.在网络上,我发现很多文档都有不好的解释和可怜的例子.我设法找到了一些有趣的话题,但所有这些话都不适合我:
"Linux系统编程" - "将文件映射到内存"部分:"调整映射大小" - 没有工作示例来调整SHM的大小.
如何实现动态共享内存大小调整? - 仅供参考.没有例子.
mremap函数无法分配新内存 - 收藏的答案有误.
c/linux - ftruncate和POSIX共享内存段 - rszshm根本不使用mremap().它复制内存.最坏的方式.
我已经开发了一个例子,因为我理解文档.不幸的是它无法正常工作.请给我一个建议,我错了.请非常友好地给我一个有效的例子.
在文档中我发现我必须在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;
}
Run Code Online (Sandbox Code Playgroud)
建立:
$ gcc -g -O0 -ggdb -pipe -Wall -Wextra -Wpedantic -Wshadow -march=native -std=c11 -o ./main ./main.c -lrt
Run Code Online (Sandbox Code Playgroud)
跑:
$ ./main
Error on mremap(): Bad address
Run Code Online (Sandbox Code Playgroud)
您正在丢失分配给的新分配/重新映射内存的地址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;
Run Code Online (Sandbox Code Playgroud)