Anonymous mappings may appear as a nullified virtual file. Anonymous mappings are simply large, zero-filled memory blocks, ready for use. These mappings are outside the heap, and therefore do not contribute to fragmentation of the data segment.
MAP_ANONYMOUS + MAP_PRIVATE:
- each call creates a clear display
- children inherit parental associations
- records of children in the inherited comparison are taken into account in copy-to-write mode
- The main purpose of using this type of matching is to allocate new zeroed memory
- malloc uses anonymous private associations to submit memory allocation requests that exceed the MMAP_THRESHOLD bytes.
typically MMAP_THRESHOLD is 128 KB.
MAP_ANONYMOUS + MAP_SHARED:
- eah call creates an excellent match that does not render pages with any other display
- children inherit parental associations
- no copy-on-write when someone else using record matching in shared mapping
- general anonymous mappings allow IPC in a manner similar to System V memory segments, but only between related processes
On Linux, there are two ways to create anonymous mappings:
specify the flag MAP_ANONYMOUS and pass -1 for fd
addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) exit(EXIT_FAILURE);
open / dev / zero and pass this open fd
fd = open("/dev/zero", O_RDWR); addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
(this method is commonly used on systems such as BSD that do not have the MAP_ANONYMOUS flag)
Benefits of Anonymous Mappings:
- lack of fragmentation of the virtual address space; after decoupling, the memory immediately returns to the system
- they change in terms of distribution size, permissions, and they can also get tips like regular comparisons
- each selection is an excellent display, separated from the global heap
Disadvantages of Anonymous Mappings:
- the size of each mapping is an integer multiple of the size of the system page, which can lead to loss of address space
- creating and returning mappings carries more overhead than from a previously allocated heap
if a program containing such a mapping produces a process, the child inherits the mapping. The following program demonstrates this inheritance:
#ifdef USE_MAP_ANON #define _BSD_SOURCE #endif #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/wait.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char *argv[]) { /*Pointer to shared memory region*/ int *addr; #ifdef USE_MAP_ANON /*Use MAP_ANONYMOUS*/ addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) { fprintf(stderr, "mmap() failed\n"); exit(EXIT_FAILURE); } #else /*Map /dev/zero*/ int fd; fd = open("/dev/zero", O_RDWR); if (fd == -1) { fprintf(stderr, "open() failed\n"); exit(EXIT_FAILURE); } addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { fprintf(stderr, "mmap() failed\n"); exit(EXIT_FAILURE); } if (close(fd) == -1) { /*No longer needed*/ fprintf(stderr, "close() failed\n"); exit(EXIT_FAILURE); } #endif *addr = 1; /*Initialize integer in mapped region*/ switch(fork()) { /*Parent and child share mapping*/ case -1: fprintf(stderr, "fork() failed\n"); exit(EXIT_FAILURE); case 0: /*Child: increment shared integer and exit*/ printf("Child started, value = %d\n", *addr); (*addr)++; if (munmap(addr, sizeof(int)) == -1) { fprintf(stderr, "munmap()() failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); default: /*Parent: wait for child to terminate*/ if (wait(NULL) == -1) { fprintf(stderr, "wait() failed\n"); exit(EXIT_FAILURE); } printf("In parent, value = %d\n", *addr); if (munmap(addr, sizeof(int)) == -1) { fprintf(stderr, "munmap()() failed\n"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); }
Sources:
Linux programming interface
Chapter 49: Memory Mappings,
Posted by: Michael Kerrisk
Linux System Programming (3rd Edition)
Chapter 8: memory management,
Posted by: Robert Love