clinuxmmapvirtual-memory

Allocate region of virtual address space upfront


I have several files that I want to map into a virtual address space consecutively with mmap(). Each file length is a multiple of the page size.

For the first file, I call mmap() with the addr parameter set to nullptr. On the next call, I set the addr parameter to the address after the end of the region that the first file was mapped to.

In some cases, I am unable to map all files because mmap() ignores the addr hint. Is there a way I can pre-allocate the entire region up front and then map the files into the region one at a time?


Solution

  • I'd like to thank @gspr for their help with this question!

    To ensure you can mmap() all of the files consecutively, you must do the following:

    1. mmap() an anonymous region with a size equal to the sum of the file sizes.
    void* ret = mmap(/*addr=*/nullptr, file_size_sum, PROT_NONE,
                     MAP_SHARED | MAP_ANONYMOUS, /*fd=*/-1, /*offset=*/0);
    assert(ret != MAP_FAILED);
    
    1. mmap() each file one at a time within the pre-allocated region. Importantly, use the MAP_FIXED flag.
    void* addr = mmap(/*addr=*/ret, file_size, PROT_READ,
                      MAP_SHARED | MAP_FIXED, fd, /*offset=*/0);
    assert(addr != MAP_FAILED);
    

    MAP_FIXED instructs mmap() to use the exact address specified in the addr parameter. If a mapping already exists for addr, the mapping is overwritten. Thus, it is important that we pre-allocate the entire region upfront in step (1) so that we do not inadvertently overwrite an existing mapping for something else in step (2) when we use MAP_FIXED.