使用Ubuntu 16.04,内核4.17.4
我正在尝试以下代码,其中定义了共享内存并将当前进程的地址空间映射到共享内存。当我在 mmap() 中使用 MAP_FIXED 时,它显示:
mmap:无效参数
代码如下:
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define STORAGE_ID "/SHM_TEST"
#define STORAGE_SIZE 4096
int main(int argc, char *argv[])
{
int res, temp;
int fd;
int len;
pid_t pid;
void *addr;
char data[STORAGE_SIZE];
fd = shm_open(STORAGE_ID, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1)
{
perror("open");
return 10;
}
res = ftruncate(fd, STORAGE_SIZE);
if (res == -1)
{
perror("ftruncate");
return 20;
}
addr = mmap(NULL, STORAGE_SIZE, PROT_WRITE, MAP_FIXED, fd, 0);
if (addr == MAP_FAILED)
{
perror("mmap");
return 30;
}
res = munmap(addr, STORAGE_SIZE);
if (res == -1)
{
perror("munmap");
return 40;
}
// shm_open cleanup
fd = shm_unlink(STORAGE_ID);
if (fd == -1)
{
perror("unlink");
return 100;
}
return 0;
}
我使用 MAP_FIXED 的原因是我将手动输入一个地址而不是
NULL
(尝试过这个并得到相同的错误)。我需要做什么才能将 MAP_FIXED
与 mmap() 一起使用?
使用 MAP_FIXED 的一种方法如下。首先,您保留一个“大”虚拟内存块:
void* virtual_address = mmap(nullptr, LargeCustomSize, PROT_READ | PROT_WRITE, MAP_NORESERVE | MAP_ANONYMOUS | MAP_SHARED, -1, 0);
这不会分配任何内存。您只需保留一系列地址
[virtual_address, virtual_address+LargeCustomsize)
。现在,保留此范围后,您可以使用 MAP_FIXED 调用单独的 mmap,以使用实际内存填充此范围内的插槽。
//Next "size_block1" will be the size of a chunk of allocated memory inside the big region
//previously reserved:
int fd = open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
ftruncate(fd,size_block1);
void* fixed_address = mmap(virtual_address, size_block1, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);
注意事项: (1)上述每次调用后都需要进行错误检查,检查errno; (2) 也可以打开/dev/hugepages(正确配置)内的文件来使用大页。在这种情况下,MAP_HUGETLB 还必须添加到 mmap 的标志列表中(例如,
MAP_NORESERVE | MAP_ANONYMOUS | MAP_SHARED | MAP_HUGETLB
)。 (3) 后续带有map_fixed的mmap将必须使用以virtual_address+size_block1
开头的地址