What is the purpose of the MAP_ANONYMOUS flag in the mmap system call?

On the man page

 MAP_ANONYMOUS The mapping is not backed by any file; its contents are initialized to zero. The fd and offset arguments are ignored; however, some implementations require fd to be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable applications should ensure this. The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux since kernel 2.4. 

What is the purpose of using MAP_ANONYMOUS ? Any example would be good. Also, where will the memory be displayed from?

The man page says that The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is only supported on Linux since kernel 2.4. How can I share memory with MAP_ANONYMOUS with another process?

+6
source share
1 answer

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

+11
source

All Articles