mmap() — Map pages of memory

Standards

Standards / Extensions C or C++ Dependencies

XPG4.2
Single UNIX Specification, Version 3
z/OS® UNIX

both  

Format

#define _XOPEN_SOURCE_EXTENDED 1
#include <sys/mman.h>

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

General description

The mmap() function establishes a mapping between an address space of a process (for len bytes) and a file associated with the file descriptor fildes at offset off for len bytes. The format of the call is as follows:

pa=mmap(addr, len, prot, flags, fildes, off); 

The value of pa is an unspecified function of the argument addr and values of flags, further described below. A successful mmap() call returns pa as its results. The address ranges covered by [pa, pa + len] and [off, off + len] must be legitimate for the possible (not necessarily current) address space of a process and the file, respectively.

If the size of the mapped file changes after the call to mmap(), the effect of references to portions of the mapped region that correspond to added or removed portions of the file is unspecified.

The prot argument determines whether read, write, execute, or some combination of accesses are permitted to the pages being mapped. The protection options are defined in <sys/mman.h>:
PROT_READ
Page can be read
PROT_WRITE
Page can be written
PROT_EXEC
Page can be executed
PROT_NONE
Page can be accessed

Implementations need not enforce all combinations of access permissions. However, write shall only be permitted when PROT_WRITE has been set.

The flags argument provides other information about the handling of the mapped pages. The options are defined in <sys/mman.h>:
MAP_SHARED
Share changes
MAP_PRIVATE
Changes are private
MAP_FIXED
Interpret addr exactly
__MAP_MEGA
Map in megabyte increments

The MAP_PRIVATE and MAP_SHARED flags control the visibility of write references to the memory region. Exactly one of these flags must be specified. The mapping type is retained across a fork.

If MAP_SHARED is set in flags, write references to the memory region by the calling process may change the file and are visible in all MAP_SHARED mappings of the same portion of the file by any process.

If MAP_PRIVATE is set in flags, write references to the memory region by the calling process do not change the file and are not visible to any process in other mappings of the same portion of the file.

All changes to the mapped data made by processes that have mapped the memory region using MAP_SHARED are shared and are visible to all other processes that have mapped the same file-offset range.

When MAP_FIXED is set in the flags argument, the implementation is informed that the value of pa must be addr, exactly. If MAP_FIXED is set, mmap() may return (void*)-1 and set errno to EINVAL. If a MAP_FIXED request is successful, the mapping established by mmap() replaces any previous mappings for the process's pages in the range [pa, pa + len].

When MAP_FIXED is not set, the implementation uses addr in an unspecified manner to arrive to pa. The pa so chosen will be an area of the address space which the implementation deems suitable for a mapping of len bytes to the file. All implementation interpret an addr value of 0 as granting the implementation complete freedom in selecting pa, subject to constraints described below. A nonzero value of addr is taken to be a suggestion of a process address near which the mapping should be placed. When the implementation selects a value for pa, it never places a mapping at address 0, nor does it replace any extant mapping, nor map into dynamic memory allocation areas.

The off argument is constrained to be aligned and sized according to the value returned by sysconf() when passed_SC_PAGESIZE or_SC_PAGE_SIZE. When MAP_FIXED is specified, the argument addr must also meet these constraints. The implementation performs mapping operations over whole pages. Thus, while the argument len need not meet a size or alignment constraint, the implementation will include, in any mapping operation, any partial page specified by the range [pa, pa + len].

The implementation always zero-fills any partial page at the end of a memory region. Further, the implementation never writes out any modified portions of the last page of a file that are beyond the end of the mapped portion of the file. If the mapping established by mmap() extends into pages beyond the page containing the last byte of the file, an application references to any of the pages in the mapping that are beyond the last page results in the delivery of a SIGBUS or SIGSEGV signal.

The mmap() function adds an extra reference to the file associated with the file descriptor fildes which is not removed by a subsequent close() on that file descriptor. This reference is removed when there are not more mappings to the file.

The st_atime field of the mapped file may be marked for update at any time between the mmap() call and the corresponding munmap() call. The initial read or write reference to a mapped region will cause the file's set_atime field to be marked for update if it has not already been marked for update.

The st_ctime and st_mtime fields of a file that is mapped with MAP_SHARED and PROT_WRITE, will be marked for update at stime point in the interval between a write reference to the mapped region and the next call to msync() with MS_ASYNC or MS_SYNC for that portion of the file by any process. If there is no such call, these fields may be marked for update at any time after a write reference if the underlying file is modified as a result.

If a memory mapped region is not unmapped before the process terminates, process termination will not automatically write out to disk any modified data in the mapped region. Modified private data in a MAP_PRIVATE region will be discarded. If the map region is MAP_SHARED, the modified data will continue to reside in the cache (if the same file-offset range is being shared) and may ultimately be written out to disk by another process using the msync() service. However, if no other processes map the same file-offset range as MAP_SHARED, the modified data is discarded.

There may be implementation-dependent limits on the number of memory regions that can be mapped (per process or per system). If such a limit is imposed, whether the number of memory regions that can be mapped by a process is decreased by the use of shmat() is implementation-dependent.

Specification of the __MAP_MEGA option results in the system allocating storage to map the file in megabyte increments. This option should only be used for large files. Any file over half a megabyte in size will likely achieve better performance by using this option. When using this option, mmaps and munmaps are in megabyte ranges on megabyte boundaries.

When __MAP_MEGA is specified, all changes to the mapped data are shared. Modifications to the mapped data are visible to all other processes that map the same file-offset range. That is, __MAP_MEGA behaves much like MAP_SHARED. __MAP_MEGA is mutually exclusive with MAP_PRIVATE and MAP_SHARED. Specification of __MAP_MEGA with either MAP_PRIVATE or MAP_SHARED will result in the request failing with errno set to EINVAL.

The __MAP_MEGA option may be specified with MAP_FIXED.

Map_address parameter: If the map address is not zero and __MAP_MEGA has been specified, then for non MAP_FIXED requests, the kernel will attempt to create the mapping at the map_address, truncated to the nearest megabyte boundary. If unsuccessful, it will proceed as if a map_address of zero were specified. For MAP_FIXED requests, the value of map_address must be multiples of the segment size (megabyte multiples). If not, the mmap request fails with errno set to EINVAL.

Map_length parameter: When __MAP_MEGA is specified, mapping operations are performed over whole segments (megabyte chunks). If the length is not a multiple of the segment size, the entire trailing portion of the last segment will also be mapped into the user storage.

File_descriptor: The file descriptor identifies the file being mapped. If an attempt is made to map a file that is already mapped but was mapped with a different specification of __MAP_MEGA, then the current request fails with errno set to EINVAL-MMapTypeMismatch. That is, at any point in time a file may be mapped with the __MAP_MEGA option or without the __MAP_MEGA option but not both ways at the same time.

For a __MAP_MEGA mapping, if this is the first map to the file represented by the specified file descriptor then whether the file was opened for read or for write will determine what protection options may be specified for the file by this mmap and any future mmaps and mprotects, by this or any other process mapping to the same file. If the file was opened for read but not write then only PROT_READ, PROT_EXEC or PROT_NONE will be allowed. If the file was opened for write, then any of the protection options will be allowed. Only regular files may be mapped. Note also that remote files accessed through NFS or DFS may not be mapped.

Protect_options: The specification made for Protect_options has a global effect when the file is mapped with the __MAP_MEGA option. The Protect_option specified immediately effects all processes currently mapped to the same file-offset range.

Large file support for z/OS UNIX files: Large z/OS UNIX files are supported automatically for AMODE 64 C/C++ applications. AMODE 31 C/C++ applications must be compiled with the option LANGLVL(LONGLONG) and define the _LARGE_FILES feature test macro before any headers are included to enable this function to operate on z/OS UNIX files that are larger than 2 GB in size. File size and offset fields are enlarged to 63 bits in width. Therefore, any other function operating on the file is required to define the _LARGE_FILES feature test macro as well.

Usage notes

  1. The mmap() function does not support shared memory objects or typed memory objects.

Returned value

If successful, mmap() returns the address at which the mapping was placed.

If unsuccessful, mmap() returns MAP_FAILED and sets errno to one of the following values:
Error Code
Description
EACCES
The fildes argument is not open for read, regardless of the protection specified, or fildes is not open for write and PROT_WRITE was specified for a MAP_SHARED type mapping.
EBADF
The fildes argument is not a valid open file descriptor.
EINVAL
The addr argument (if MAP_FIXED was specified) or off is not a multiple of the page size as returned by sysconf(), or are considered invalid by the implementation.

The value of flags is invalid (neither MAP_PRIVATE nor MAP_SHARED is set).

EMFILE
The number of mapped regions would exceed an implementation-dependent limit (per process or per system).
ENODEV
The fildes argument refers to a file whose type is not supported by mmap().
ENOMEM
MAP_FIXED was specified, and the range [addr, addr + range [addr, addr + len], rounding len] exceeds that allowed for the address space for a process; or if MAP_FIXED was not specified and there is insufficient room in the address space to effect the mapping.
ENXIO
Address in the range [off, off + len] are invalid for fildes
EOVERFLOW
The file is a regular file and the value of off plus len exceeds the offset maximum established in the open file.
Note: Starting with z/OS V1.9, environment variable _EDC_EOVERFLOW can be used to control behavior of mmap() with respect to detecting an EOVERFLOW condition for z/OS UNIX files. By default, mmap() will not set EOVERFLOW when the offset maximum is exceeded associated with fildes. When _EDC_EOVERFLOW is set to YES, mmap() will check for an overflow condition.

Related information