为什么 mmap 在使用 MAP_FIXED 时会抛出错误?

问题描述 投票:0回答:1

使用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() 一起使用?

linux mmap
1个回答
0
投票

使用 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

开头的地址
© www.soinside.com 2019 - 2024. All rights reserved.