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 );

Arguments:

addr
NULL, or a pointer to where you want the object to be mapped in the calling process's address space.
len
The number of bytes to map into the caller's address space. It can't be 0.
prot
The access capabilities that you want to use for the memory region being mapped. You can combine at least the following protection bits, as defined in <sys/mman.h>:
  • PROT_EXEC — the region can be executed.

    In order to successfully use this flag:

    • Your process must have the PROCMGR_AID_PROT_EXEC ability enabled. For more information, see procmgr_ability() .
    • If your process has any privileged abilities enabled, then any memory-mapped files in the region must be from a trusted filesystem. For more information, see pathtrust in the Utilities Reference.

  • PROT_NOCACHE — disable caching of the region (e.g. so it 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
Flags that specify further information about handling the mapped region. POSIX defines the following:
  • MAP_PRIVATE
  • MAP_SHARED
  • MAP_FIXED

The following are Unix or BlackBerry 10 OS extensions:

  • MAP_ANON
  • MAP_BELOW
  • MAP_BELOW16M
  • MAP_ELF
  • MAP_FILE — defined for compatibility; has no effect.
  • MAP_LAZY
  • MAP_NOINIT
  • MAP_RENAME — defined for compatibility; has no effect.
  • MAP_NORESERVE — defined for compatibility; has no effect.
  • MAP_NOSYNCFILE
  • MAP_NOX64K
  • MAP_PHYS
  • MAP_STACK

For more information, see below.

fildes
The file descriptor for a file, shared memory object, or typed memory object. If you're mapping anonymous or physical memory, this argument must be NOFD.
off
The offset into the file or memory object of the region that you want to start mapping, or a physical address (e.g. for mapping a device's registers in a resource manager).

If you want to map a device's physical memory, use mmap_device_memory() instead of mmap().

On x86, if a device's registers are memory-mapped, you can use mmap_device_memory() to access them. Otherwise you can use mmap_device_io() to gain access to the device, and routines such as in8() and out8() to access them. On architectures other than the x86, both methods are equivalent.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

Description:

The mmap() and mmap64() functions map a region within the object specified by filedes, beginning at off and continuing for len, into the caller's address space and returns the location. The mmap64() function is a 64-bit version of mmap(). The object that you map from can be one of the following:

If fildes isn't NOFD, you must have opened the file descriptor for reading, no matter what value you specify for prot; write access is also required for PROT_WRITE if you haven't specified MAP_PRIVATE.

The mapping is as shown below.

Diagram that shows how memory is mapped using the mmap()function.

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 on whether or not you set MAP_FIXED 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 as to where to map the object in the calling process's address space. The mapped area won't overlay any current mapped areas.

There are two parts to the flags parameter. The first part is a type (masked by the MAP_TYPE bits), which is maintained across a fork() . You must specify one of the following types:

MAP_PRIVATE
The mapping is private to the calling process; changes aren't propagated back to the underlying object. For this type of mapping, mmap() allocates system RAM and copies the current object.
MAP_SHARED
The mapping may be shared by many processes; changes are propagated back to the underlying object.

You can OR the following flags into the above type to further specify the mapping:

MAP_ANON
Map anonymous memory that isn't associated with a specific file descriptor; the fildes parameter must be NOFD. The mmap() function allocates the memory and fills it with zeros, unless you've also specified MAP_NOINIT (see below). This is equivalent to opening /dev/zero.

MAP_ANON is most commonly used with MAP_PRIVATE, but you can use it with MAP_SHARED to create a shared memory area for forked applications.

MAP_BELOW
Map below the given addr, if possible.
MAP_BELOW16M
Used with MAP_PHYS | MAP_ANON. The allocated memory area resides in physical memory below 16 MB. This is important for using DMA with ISA bus devices.
MAP_ELF
The memory is an ELF object. This flag is used by the program loader.
MAP_FILE
Map a regular file. This flag is required on some operating systems, but is optional on BlackBerry 10 OS.

You can have more than one writeable mapping to a file. If you access the file via file descriptors as well as via the memory mapping, you'll have to be careful to keep the file's contents coherent. For example, you should specify O_SYNC when you open() the file.

MAP_FIXED
Map the object to the address specified by addr. If this area is already mapped, the call changes the existing mapping of the area.

  • In order to use MAP_FIXED, your process must have the PROCMGR_AID_MAP_FIXED ability enabled. For more information, see procmgr_ability() .
  • Use MAP_FIXED with caution. Not all memory models support it. In general, you should assume that you can MAP_FIXED only at an address (and size) that a call to mmap() without MAP_FIXED returned.

A memory area being mapped with MAP_FIXED is first unmapped by the system using the same memory area. See munmap() for details.

MAP_LAZY
Delay acquiring system memory, and copying or zero-filling the MAP_PRIVATE or MAP_ANON pages, until an access to the area has occurred. If you set this flag, and there's no system memory at the time of the access, the thread gets a SIGBUS with a code of BUS_ADRERR. This flag is a hint to the memory manager.

For anonymous shared memory objects (those created via mmap() with MAP_ANON | MAP_SHARED and a file descriptor of -1), a MAP_LAZY flag implicitly sets the SHMCTL_LAZY flag on the object (see shm_ctl() ).

MAP_NOINIT
Relax the POSIX requirement that the memory be zeroed. The physical memory being used for this allocation must have been previously freed with UNMAP_INIT_OPTIONAL for this flag to have any effect.
MAP_RENAME
Defined for compatibility, but has no effect.
MAP_NORESERVE
Defined for compatibility, but has no effect.
MAP_NOSYNCFILE
Don't update the underlying file.

If the same region in a file is mapped twice, once with MAP_NOSYNCFILE and once without, the memory manager might not be able to tell whether a change was made through the MAP_NOSYNCFILE mapping or not, and thus write out changes that weren't intended.

MAP_NOX64K
(Useful on x86 only). Used with MAP_PHYS | MAP_ANON. Prevent the allocated memory area from crossing a 64 KB boundary. This may be important to some DMA devices. If more than 64 KB is requested, the area begins on a 64 KB boundary.
MAP_PHYS
Physical memory is required. The fildes parameter must be NOFD. When you use this flag without MAP_ANON, the offset specifies the exact physical address to map (e.g. for video frame buffers), and is equivalent to opening /dev/mem.

If you use MAP_PHYS with MAP_ANON, mmap() allocates physically contiguous memory and ignores the offset. You can use MAP_NOX64K and MAP_BELOW16M to further define the MAP_ANON allocated memory (useful on x86 only).

  • In order to use MAP_PHYS, your process must have the PROCMGR_AID_MEM_PHYS ability enabled. For more information, see procmgr_ability() .
  • You should use mmap_device_memory() instead of MAP_PHYS, unless you're allocating physically contiguous memory.

MAP_STACK
This flag tells the memory allocator what the MAP_ANON memory will be used for. It's only a hint.

The following flags are defined in <sys/mman.h>, but you shouldn't use them:

MAP_PRIVATEANON
Deprecated; use MAP_PRIVATE | MAP_ANON instead.
MAP_SYSRAM
An output-only status flag for the DCMD_PROC_MAPINFO and DCMD_PROC_PAGEDATA devctl() commands. For more information, see " Controlling processes via the /proc filesystem " in the Processes chapter of the BlackBerry 10 OS Programmer's Guide.

Specifying the MAP_SYSRAM bit in a call to mmap() will result in an error of EINVAL.

If fildes represents a typed memory object opened with either the POSIX_TYPED_MEM_ALLOCATE or POSIX_TYPED_MEM_ALLOCATE_CONTIG flag (see posix_typed_mem_open() ), and there are enough resources available, mmap() maps len bytes allocated from the corresponding typed memory object that weren't previously allocated to any process in any processor that may access that typed memory object. If there aren't enough resources available, mmap() fails.

If fildes represents a typed memory object opened with the POSIX_TYPED_MEM_ALLOCATE_CONTIG flag, the allocated bytes are contiguous within the typed memory object. If the typed memory object wase opened with POSIX_TYPED_MEM_ALLOCATE, the allocated bytes may be composed of noncontiguous fragments within the typed memory object. If the typed memory object was opened with neither of these flags, len bytes starting at the given offset within the typed memory object are mapped, exactly as when mapping a file or shared memory object. In this case, if two processes map an area of typed memory using the same offset and length and using file descriptors that refer to the same memory pool (either from the same port or from a different port), both processes map the same region of storage.

Returns:

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

Errors:

EACCES
One of the following occurred:
  • The file descriptor in fildes isn't open for reading.
  • You specified PROT_WRITE and MAP_SHARED, and fildes isn't open for writing.
  • You specified PROT_EXEC for a memory-mapped file mapping, the file doesn't have execute permission for the client process, and procnto was started with the -mX option.
EAGAIN
The mapping couldn't be locked in memory, if required by mlockall() , because of a lack of resources.
EBADF
Invalid file descriptor, fildes.
EBUSY
The resource you're trying to map is busy.
EINVAL
The type specified in flags is invalid, len is 0, or you specified MAP_FIXED and addr is invalid.
EMFILE
The number of mapped regions has reached the maximum limit; see the RLIMIT_AS and RLIMIT_DATA resources for setrlimit() .
ENODEV
The fildes argument refers to an object for which mmap() is meaningless (e.g. a terminal).
ENOMEM
One of the following occurred:
  • You specified MAP_FIXED, and the address range requested is outside of the allowed process address range, or there wasn't enough memory to satisfy the request.
  • The mapping couldn't be locked in memory, if required by mlockall() , because there wasn't enough memory.
  • There aren't enough unallocated resources remaining in the typed memory object associated with the file descriptor.
ENXIO
One of the following occurred:
  • Addresses in the range [off, off+len) are invalid for the object specified by fildes.
  • You specified MAP_FIXED, and addr, len, and off are invalid for the requested object.
  • The file descriptor refers to a typed memory object that the calling process can't access.
EOVERFLOW
The file is a regular file, and the offset plus the length exceeds the maximum offset.
EPERM
The calling process doesn't have the required permission (see procmgr_ability() ), or it attempted to set PROT_EXEC for a region of memory covered by an untrusted memory-mapped file.

Examples:

Open a shared memory object and share it with other processes:

fd = shm_open( "/datapoints", O_RDWR, 0777 );
addr = mmap( 0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0 );

Allocate a physically contiguous DMA buffer for a bus-mastering PCI network card:

addr = mmap( 0,
             262144,
             PROT_READ|PROT_WRITE|PROT_NOCACHE,
             MAP_PHYS|MAP_ANON,
             NOFD,
             0 );

Map a file into memory, change the memory, and then verify that the file's contents have been updated:

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

#define TESTSTRING "AAAAAAAAAA"

int main(int argc, char *argv[]) {
    char buffer[80], filename[200] = "/tmp/try_it";
    int fd, file_size, ret, size_written, size_read;
    void *addr;
    
    /* Write the test string into the file. */
    unlink( filename);
    fd = open( filename, O_CREAT|O_RDWR , 0777 );
    if( fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    size_written = write( fd, TESTSTRING, sizeof (TESTSTRING) );
    if ( size_written == -1 ){
        perror("write");
        exit(0);
    }   
    printf( "Wrote %d bytes into file %s\n", size_written, filename );
    
    lseek( fd, 0L, SEEK_SET );
    file_size = lseek( fd, 0L, SEEK_END );
    printf( "Size of file = %d bytes\n", file_size );

    /* Map the file into memory. */
    addr = mmap( 0, file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
                 fd, 0 );
    if (addr == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    } 

    /* Change the memory and synchronize it with the disk. */
    memset( addr, 'B', 5 );
    ret = msync( addr, file_size, MS_SYNC);
    if( ret == -1) {
        perror("msync");
        exit(0);
    }
    
    /* Close and reopen the file, and then read its contents. */
    close(fd);
    fd = open( filename, O_RDONLY);
    if( fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    size_read = read( fd, buffer, sizeof( buffer ) );
    printf( "File content = %s\n", buffer );
    
    close(fd);
    return EXIT_SUCCESS;
}

Classification:

mmap() is POSIX 1003.1 MF|SHM|TYM; mmap64() is Large-file support

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

Last modified: 2013-12-23

comments powered by Disqus