Brain Dump

mmap

Tags
comp-arch

Is a system-call that allows you map pages into memory and share them with child processes. The memory for this could come from a file stored on a disk or from a shared or typed memory object. See mmap and munmap.

// Open the file to mmap.
int fd = open(argv[1], O_RDWR);
// Stat it to get its file size.
size_t length;
struct stat sb;
fstat(fd, &sb);
// Must be a multiple of the page size for the system.
off_t offset;
off_t page_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
// mmap into our processes memory.
char *addr = mmap(NULL, length + offset - page_offset, PROT_READ|PROT_WRITE,
		  MAP_PRIVATE, fd, page_offset);
// Write the body of the file to stdout.
write(1, addr + offset - page_offset, length);
// Unmmap and close the file descriptor.
munmap(addr, length + offset - pa_offset);
close(fd);
Code Snippet 1: An example of memory mapping a file into memory and writing its contents out to stdout.
Table 1: Possible flags for the prot parameter of mmap. Many of these may require the underlying file descriptor to be opened with read or write privileges.
Symbolic ConstantDescription
PROT_READData can be read
PROT_WRITEData can be written
PROT_EXECData can be executed (conflicts with PROT_WRITE)
PROT_NONEData cannot be accessed (takes precedence over PROT_WRITE)
MAP_SHAREDMapping will be synced with the file object
MAP_PRIVATEMapping won't be visible to the process itself

Note: PROT_NONE may seem sort of useless however it's useful for securing a system. If you prefix and suffix pages containing sensitive information with guard pages then you decrease the changes of an attack.

Communicating With Sub-processes

Memory mapped through mmap can be accessed through sub-processes directly.

// mmap an array of 100 pointers with no file descriptor.
int size = 100 * sizeof(int);
void *addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
int *shared = addr;

// Fork an modify the value in a subprocess, then print in the parent process.
pid_t mychild = fork();
if (mychild > 0) {
    shared[0] = 10;
    shared[1] = 20;
} else {
    sleep(1); // Check the synchronization chapter for a better way
    printf("%d\n", shared[1] + shared[0]);
}

// Cleanup
munmap(addr, size);
Code Snippet 2: An example of a child modifying data mmaped into it by its parent.

Links to this note