A simple mmap() readonly example

Problem:

You want to use mmap() from sys/stat.h POSIX header to map a file for reading (not writing). You can’t find any simple bare example on the internet.

Solution

If you’re only interest in a high-level wrapper, please have a look at this boost::iostreams mmap example and the boost::iostreams mmap reference. Keep in mind, however, boost::iostreams does not provide all functionality mmap() does and boost::iostreams is quite a large dependency (you need to link the library!). However, it might be the best option for better portability to non-unix systems.

Here’s a minimal mmap() based cat implementation. It is not efficient, but demonstrates the important concepts. It uses the stat()-based getFilesize() function from this previous post

#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <assert.h>

size_t getFilesize(const char* filename) {
    struct stat st;
    stat(filename, &st);
    return st.st_size;
}

int main(int argc, char** argv) {
    size_t filesize = getFilesize(argv[1]);
    //Open file
    int fd = open(argv[1], O_RDONLY, 0);
    assert(fd != -1);
    //Execute mmap
    void* mmappedData = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE | MAP_POPULATE, fd, 0);
    assert(mmappedData != MAP_FAILED);
    //Write the mmapped data to stdout (= FD #1)
    write(1, mmappedData, filesize);
    //Cleanup
    int rc = munmap(mmappedData, filesize);
    assert(rc == 0);
    close(fd);
}

Compile using

g++ -o mmap-example mmap-example.cpp

Run like this:

echo "hello mmap world" > test.txt
./mmap-example test.txt

Step-by-step discussion

Step 1: Get the filesize. You need to know that before calling mmap, but you can also mmap a subset only.

Step 2: Open the file. Keep in mind you can’t use the fopen() function directly (you could use fileno() on the FILE object) because you need the file descriptor! In this case we’re using O_RDONLY because we want to mmap() read-only.

Step 3: Call mmap() with those parameters:

For a detailed mmap() reference, see the Opengroup page on mmap

Error-checking

The above implementation does not properly check for errors because it’s only a minimal example.

In any case, you should at least check if the value returned by mmap() is == MAP_FAILED. See the Opengroup page on mmap for details.

Update 2013/09/26: Close the file descriptor in cleanup section Update 2016/01/07: assert != MAP_FAILED instead of NULL (Thanks to Erik Sjölund)