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.
    
    Note: 
    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 
    (on some hardware architectures, PROT_WRITE also implies PROT_READ).
     
    Note: 
    In order to simultaneously set  PROT_EXEC and  PROT_WRITE,
    your process must have the  PROCMGR_AID_PROT_WRITE_AND_EXEC ability enabled
    (in addition to  PROCMGR_AID_PROT_EXEC).
    For more information, see
     procmgr_ability().
    
     
 
 
- 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 QNX Neutrino extensions:
   
  - MAP_ANON
- MAP_BELOW
- MAP_ELF
- MAP_FILE — defined for compatibility; has no effect.
- MAP_LAZY
- MAP_NORESERVE — defined for compatibility; has no effect.
- MAP_NOSYNCFILE
- MAP_PHYS
- MAP_RENAME — defined for compatibility; has no effect.
- 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).
  Note: 
  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 large-file support version of mmap().
Note: 
In QNX Neutrino 6.6 or later, the large-file support functions and data types
appear in the name space only if you define 
_LARGEFILE64_SOURCE when you compile your code.
For more information, see
Classification
in What's in a Function Description?
 
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:
 Figure 1. Mapping memory with mmap().
Figure 1. Mapping memory with mmap(). 
Typically, you don't need to use addr; you can just pass
NULL instead.
Mappings, including the flags, are maintained across a
fork().
The flags argument includes a type (masked by the MAP_TYPE bits)
and additional bits.
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.
  
Note: 
- Don't have a shared, writable mapping to a file that you're simultaneously accessing via
  write().
  The interaction between the two methods isn't well defined and may give unexpected results.
- 
In QNX Neutrino 7.0 and later, if you don't specify either MAP_PRIVATE or MAP_SHARED,
mmap() returns MAP_FAILED and sets errno to EINVAL.
 
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.
  
  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.
  The addr argument to mmap() is a hint as to
  where to put the mapped region in the caller's address space (unless
  combined with MAP_FIXED, which turns it into a strong requirement).
  MAP_BELOW changes the meaning of the hint to be where the region should
  end instead of where it should begin.  - If MAP_BELOW is set, the memory manager searches downwards, proceeding
    to the bottom of the address space, and may wrap around if no hole of the required size
    is available. Therefore, the mapping may be made at an address larger than addr. - If MAP_BELOW isn't set, the memory manager searches upwards, proceeding to the top, and may wrap around
    if necessary. Therefore, the mapping may be made at an address smaller than addr.
     
- 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 has no effect on
  QNX Neutrino.
  
- MAP_FIXED
- Map the object to the address specified by addr, or the function fails.
  If this area is already mapped, the call changes the existing mapping of the area. 
  A memory area being mapped with MAP_FIXED is first unmapped
  by the system using the same memory area.  
  See
  munmap() 
  for details.
  
  Note: 
  
  - 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 because it
    removes any existing mappings, making it easy for a multithreaded process to corrupt its own address space.
    In general, you should assume that you can use MAP_FIXED
  only at an address (and size) that a call to
  mmap() without MAP_FIXED returned.
  
 
 
  If addr isn't NULL, and you don't set MAP_FIXED, then
  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. Refer to the MAP_BELOW
  description for information on what happens if the hint in addr can't be followed.
   
- 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_OBJERR.
  This flag is a hint to the memory manager. 
  
  
  
  
  
- MAP_NORESERVE
- Defined for compatibility, but has no effect.
  
- MAP_NOSYNCFILE
- Don't update the underlying file.
  
  Note: 
  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_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 should almost always use these flags with MAP_SHARED;
  if you use them with MAP_PRIVATE and then fork(), then
  when the parent or child privatizes a page, you'll get a new physical page, and the
  entire range will no longer be contiguous.
  
  
   Note: 
  In order to use  MAP_PHYS to map physical memory, your process must have the
     PROCMGR_AID_MEM_PHYS ability enabled; you don't need this ability if you also
    specify  MAP_ANON.
    For more information, see
     procmgr_ability().
    
   
 
- MAP_RENAME
- Defined for compatibility, but has no effect.
  
- MAP_STACK
- This flag tells the memory allocator what the MAP_ANON memory will be used for. 
  It's only a hint.
  
The following flag is defined in <sys/mman.h>, but
you shouldn't use it:
- 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 QNX Neutrino Programmer's Guide.
  
  
  
  Note: 
  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
- One of the following occurred:
  
  - The len argument is 0.
- The prot argument is invalid.
- (QNX Neutrino 7.0 or later) You didn't specify MAP_PRIVATE or MAP_SHARED.
- You included MAP_SYSRAM in the flags.
    This bit is an output-only status flag for the DCMD_PROC_MAPINFO and
    DCMD_PROC_PAGEDATA devctl() commands.
  
- You specified MAP_PHYS with MAP_PRIVATE, and you aren't using the
    backward-compatibility memory-manager option (procnto -m~b).
    If you're using the backward-compatibility memory-manager option (procnto -mb),
    mmap() assumes you meant MAP_SHARED.
    
  
- You specified MAP_ANON or MAP_PHYS, and filedes
    isn't NOFD.
  
- You specified both MAP_LAZY and MAP_PHYS.
    Requesting lazy allocation of physically contiguous memory is asking for trouble.
  
- You specified MAP_PHYS, and the object goes beyond the last physical address that
    the architecture supports.
  
- (QNX Neutrino 6.6 or later) The sum of the offset and the length of the required memory object
    wraps around past 0.
  
 
- 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_SHARED | 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;
}