调整 POSIX 共享内存的大小。一个工作示例
Resize POSIX shared memory. A working example
我在两个不同应用程序之间的 POSIX 模型中有一个共享动态数组。我希望能够在不复制的情况下更改其大小。不幸的是,我找不到正确的解决方案来增加和减少 C 语言中的 POSIX 共享内存。在网络上,我发现许多文档的解释很差,例子也很糟糕。我设法找到了一些有趣的主题,但它们都不适合我:
"Linux System Programming" - "Mapping Files into Memory" Part: "Resizing a Mapping" - 没有调整 SHM 大小的工作示例。
How do I implement dynamic shared memory resizing? - 仅作描述。没有例子。
mremap function failed to allocate new memory - 最喜欢的答案有误。
Fast resize of a mmap file
Characteristics of mremap function in Linux
mremap function failed to allocate new memory
c/linux - ftruncate and POSIX Shared Memory Segments - 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;
}
建造:
$ gcc -g -O0 -ggdb -pipe -Wall -Wextra -Wpedantic -Wshadow -march=native -std=c11 -o ./main ./main.c -lrt
运行:
$ ./main
Error on mremap(): Bad address
您正在丢失分配给 temp
的新 allocated/remapped 内存的地址。
这意味着,从 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;
我在两个不同应用程序之间的 POSIX 模型中有一个共享动态数组。我希望能够在不复制的情况下更改其大小。不幸的是,我找不到正确的解决方案来增加和减少 C 语言中的 POSIX 共享内存。在网络上,我发现许多文档的解释很差,例子也很糟糕。我设法找到了一些有趣的主题,但它们都不适合我:
"Linux System Programming" - "Mapping Files into Memory" Part: "Resizing a Mapping" - 没有调整 SHM 大小的工作示例。
How do I implement dynamic shared memory resizing? - 仅作描述。没有例子。
mremap function failed to allocate new memory - 最喜欢的答案有误。
Fast resize of a mmap file
Characteristics of mremap function in Linux
mremap function failed to allocate new memory
c/linux - ftruncate and POSIX Shared Memory Segments - 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;
}
建造:
$ gcc -g -O0 -ggdb -pipe -Wall -Wextra -Wpedantic -Wshadow -march=native -std=c11 -o ./main ./main.c -lrt
运行:
$ ./main
Error on mremap(): Bad address
您正在丢失分配给 temp
的新 allocated/remapped 内存的地址。
这意味着,从 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;