[Previous] [Contents] [Next]

mmap(), mmap64()

Map a memory region into a process's address space

Synopsis:

#include <sys/mman.h>

void * mmap( void * addr,
             size_t len,
             int prot,
             int flags,
             int fildes,
             off_t off );

void * mmap64( void * addr,
               size_t len,
               int prot,
               int flags,
               int fildes,
               off64_t off );

Library:

libc

Description:

A region within the object beginning at off and continuing for len bytes is mapped into the caller's address space at the location returned by the mmap() function.

The arguments are as follows:

addr
Where the object should be mapped in the calling process's address space (typically, you don't need to use addr, you can just pass NULL instead). If you set addr to a non-NULL value, whether the object is mapped depends if MAP_FIXED is set in flags.
MAP_FIXED is set
The object is mapped to the address in addr, or the function fails.
MAP_FIXED isn't set
The value of addr is taken as a hint to where the object should be mapped in the calling process's address space. The mapped area won't overlay any current mapped areas.
len
Number of bytes to map into the caller's address space.
prot
Specifies the access capabilities for the memory region being mapped. At least the following protection bits may be combined, as defined in <sys/mman.h>:
Protection Description
PROT_EXEC The region can be executed.
PROT_NOCACHE Disable caching of the region (e.g. can be used to access dual-ported memory).
PROT_NONE The region can't be accessed.
PROT_READ The region can be read.
PROT_WRITE The region can be written.
flags
Specifies further information about handling the mapped region. There are two parts to the flags parameter. The first part is a type (masked by the MAP_TYPE bits) and must be specified as one of the following:
Map type Description
MAP_ANON Similar to MAP_PRIVATE but the fildes parameter must be NOFD. The allocated memory is zero-filled. This is equivalent to opening /dev/zero and mapping it with MAP_PRIVATE.
MAP_PRIVATE The mapping is private to the calling process. It allocates system RAM and copies the current object.
MAP_SHARED The mapping may be shared by many processes.

The following flags may be ORed in to the above type to further define the mapping:

Map type Description
MAP_BELOW16M Used with MAP_PHYS | MAP_ANON. The allocated memory area resides in physical memory below 16M. This is important for using DMA with ISA bus devices.
MAP_FIXED Map object to the address specified by addr. If this area is already mapped, the call changes the existing mapping of the area. MAP_FIXED should be used with caution. Not all memory models will support it. In general, you should only assume that you can MAP_FIXED at an address (and size) which was returned by calling mmap() without MAP_FIXED in your code.

A memory area being mmap()'d with MAP_FIXED will first be munmap()'d by the system using the same memory area. See munmap() for details.

MAP_LAZY Acquiring system memory and copying, or zero filling, the MAP_PRIVATE or MAP_ANON pages can be delayed until an access to the area has occurred. If this is set and there's no system memory at the time of the access, the thread will get a SIGBUS with a code of BUS_ADRERR. A hint to the memory manager.
MAP_PHYS Specifies that physical memory is required. The fildes parameter must be NOFD. When used with MAP_PRIVATE or MAP_SHARED, the offset specifies the exact physical address to map (e.g. for video frame buffers), and is equivalent to opening /dev/mem. If used with MAP_ANON, then physically contiguous memory is allocated.

MAP_NOX64K and MAP_BELOW16M are used to further define the MAP_ANON allocated memory (useful on x86 only).

You should use mmap_device_memory() instead of MAP_PHYS.

MAP_NOX64K (Useful on x86 only). Used with MAP_PHYS | MAP_ANON. The allocated memory area won't cross a 64K boundary. This may be important to some DMA devices. If more than 64K is requested, the area begins on a 64K boundary.
MAP_STACK (Useful on x86 only). This flag tells the memory allocator what the MAP_ANON memory will be used for. It's only a hint.

Using the mapping flags described above, a process can easily share memory between processes:

/* Map in a shared memory region */
fd = shm_open( "/datapoints", O_RDWR, 0777 );
addr = mmap( 0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );

Or share memory with hardware such as video memory on an x86 platform:

/* Map in VGA display memory */
addr = mmap( 0,
             65536,
             PROT_READ|PROT_WRITE,
             MAP_PHYS|MAP_SHARED,
             NOFD,
             0xa0000 );

Or allocate a DMA buffer for a bus-mastering PCI network card:

/* Allocate a physically contiguous buffer */
addr = mmap( 0,
             262144,
             PROT_READ|PROT_WRITE|PROT_NOCACHE,
             MAP_PHYS|MAP_ANON,
             NOFD,
             0 );

Returns:

The address of the mapped-in object, or MAP_FAILED if an error occurred (errno is set).

Errors:

EACCES
The file descriptor in fildes isn't open for read, or PROT_WRITE and MAP_SHARED was specified and fildes wasn't open for write.
EBADF
Invalid file descriptor, fildes.
EINVAL
Invalid flags type.
ENODEV
The fildes argument refers to an object for which mmap() is meaningless (e.g. a terminal).
ENOMEM
MAP_FIXED was specified and the address range requested is outside of the allowed process address range, or there wasn't enough memory to satisfy the request.
ENXIO
The address from off for len bytes is invalid for the requested object, or MAP_FIXED was specified and addr, len, and off are invalid for the requested object.

Examples:

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/mman.h>

main()
{
  int          i;
  unsigned char         *addr, c;

  /* Map BIOS ROM */
  addr = mmap(0, 0x10000, PROT_READ | PROT_WRITE,
               MAP_SHARED | MAP_PHYS, NOFD, 0xf0000);
  if (addr == MAP_FAILED) {
    fprintf(stderr, "mmap failed : %s\n",
     strerror(errno));
     return EXIT_FAILURE;
  }
  printf("Map addr is %6.6X\n", addr);

  for (i = 0; i < 3 * 80; ++i) {
     c = *addr++;
     if (c >= ' ' && c <= 0x7f)
       putchar(c);
     else
       putchar('.');
  }

  return EXIT_SUCCESS;
}

Classification:

mmap() is POSIX 1003.1; mmap64() is for large-file support

Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes

See also:

mmap_device_memory(), munmap()


[Previous] [Contents] [Next]