linuxprocessipcmmap

mmap File-backed mapping vs Anonymous mapping in Linux



Solution

  • mmap() system call allows you to go for either file-backed mapping or anonymous mapping.

    void *mmap(void *addr, size_t lengthint " prot ", int " flags ,int fd, off_t offset)

    File-backed mapping- In linux , there exists a file /dev/zero which is an infinite source of 0 bytes. You just open this file, and pass its descriptor to the mmap() call with appropriate flag, i.e., MAP_SHARED if you want the memory to be shared by other process or MAP_PRIVATE if you don't want sharing.

    Ex-

         .
         .
    if ((fd = open("/dev/zero", O_RDWR)) < 0)
    printf("open error");
    if ((area = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0)) == MAP_FAILED)
      {
          printf("Error in memory mapping");
          exit(1);
      }
    close(fd); //close the file because memory is mapped
      //create child process 
        .
        .
    

    Quoting the man-page of mmap() :-

    The contents of a file mapping (as opposed to an anonymous mapping; see MAP_ANONYMOUS below), are initialized using length bytes starting at offset offset in the file (or other object) referred to by the file descriptor fd. offset must be a multiple of the page size as returned by sysconf(_SC_PAGE_SIZE).

    In our case, it has been initialized with zeroes(0s).

    Quoting the text from the book Advanced Programming in the UNIX Environment by W. Richard Stevens, Stephen A. Rago II Edition

    The advantage of using /dev/zero in the manner that we've shown is that an actual file need not exist before we call mmap to create the mapped region. Mapping /dev/zero automatically creates a mapped region of the specified size. The disadvantage of this technique is that it works only between related processes. With related processes, however, it is probably simpler and more efficient to use threads (Chapters 11 and 12). Note that regardless of which technique is used, we still need to synchronize access to the shared data

    After the call to mmap() succeeds, we create a child process which will be able to see the writes to the mapped region(as we specified MAP_SHARED flag).

    Anonymous mapping - The similar thing that we did above can be done using anonymous mapping.For anonymous mapping, we specify the MAP_ANON flag to mmap and specify the file descriptor as -1. The resulting region is anonymous (since it's not associated with a pathname through a file descriptor) and creates a memory region that can be shared with descendant processes. The advantage is that we don't need any file for mapping the memory, the overhead of opening and closing file is also avoided.

    if ((area = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0)) == MAP_FAILED)
       printf("Error in anonymous memory mapping");
    

    So, these file-backed mapping and anonymous mapping necessarily work only with related processes.

    If you need this between unrelated processes, then you probably need to create named shared memory by using shm_open() and then you can pass the returned file descriptor to mmap().