HPlogo HP-UX Reference Volume 3 of 5 > m

mmap(2)

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

NAME

mmap — map pages of memory

SYNOPSIS

#include <sys/mman.h> void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

DESCRIPTION

Note: This manpage contains HP-UX extensions.

The mmap() function establishes a mapping between a process' address space and a file. The format of the call is as follows:

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

The mmap() function establishes a mapping between the process' address space at an address pa for len bytes and the file associated with the file descriptor fildes at offset off for len bytes. 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 result. 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 mmap() function is supported for regular files. Support for any other type of 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 cannot be accessed.

Implementations need not enforce all combinations of access permissions. However, writes 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_ADDR32

Share changes between 32-bit and 64-bit processes.

MAP_PRIVATE

Changes are private.

MAP_FIXED

Interpret addr exactly.

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 of the same executable type. That is, an application compiled as a 32-bit process will be able to share the same mappings with other 32-bit processes, and an application compiled as a 64-bit process will be able to share the same mappings with other 64-bit processes.

If a 64-bit and a 32-bit application want to share the same mapping, both MAP_ADDR32 and MAP_SHARED must be set in flags by the 64-bit application. The 32-bit application does not need to set MAP_ADDR32 in flags. When MAP_SHARED is set in flags, write references to the memory region by the calling process may change the file. Changes are visible in all 32-bit processes which specify MAP_SHARED and by all 64-bit processes which specify both MAP_SHARED and MAP_ADDR32 for the same portion of the file.

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.

It is unspecified whether write references by processes that have mapped the memory region using MAP_SHARED are visible to processes that have mapped the same portion of the file using MAP_PRIVATE.

It is also unspecified whether write references to a memory region mapped with MAP_SHARED are visible to processes reading the file and whether writes to a file are visible to processes that have mapped the modified portion of that file, except for the effect of msync().

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 MAP_FAILED and set errno to EINVAL. If a MAP_FIXED request is successful, the mapping established by mmap() replaces any previous mappings for the process' pages in the range [pa, pa+len].

When MAP_FIXED is not set, the implementation uses addr in an unspecified manner to arrive at 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 implementations interpret an addr value of 0 as granting the implementation complete freedom in selecting pa, subject to constraints described below. A non-zero 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 unmapping 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 reference 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 no 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 st_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 some 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.

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.

RETURN VALUE

Upon successful completion, mmap() returns the address, (pa), at which the mapping was placed. Otherwise, it returns MAP_FAILED (defined in <sys/mman.h>) and sets errno to indicate the error.

ERRORS

The mmap() function will fail if:

[EBADF]

The fildes argument is not a valid open file descriptor.

[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.

[ENXIO]

Addresses in the range [off, off+len] are invalid for fildes.

[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.

[EINVAL]

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

[EINVAL]

The mapping already exists in 64-bit address space, but the application performing the current mmap() request has been compiled as a 32-bit executable.

[EINVAL]

The mapping already exists in 32-bit address space, but the application performing the current mmap() request has been compiled as a 64-bit executable and did not specify MAP_ADDR32 in the flags argument.

[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+len] exceeds that allowed for the address space of a process; or if MAP_FIXED was not specified and there is insufficient room in the address space to effect the mapping.

APPLICATION USAGE

Use of mmap() may reduce the amount of memory available to other memory allocation functions.

Use of MAP_FIXED may result in unspecified behavior in further use of brk(), sbrk(), malloc(), and shmat(). The use of MAP_FIXED is discouraged, as it may prevent an implementation from making the most effective use of resources.

The application must ensure correct synchronization when using mmap() in conjunction with any other file access method, such as read() and write(), standard input/output, and shmat().

The mmap() function allows access to resources via address space manipulations, instead of read()/write(). Once a file is mapped, all a process has to do to access it is use the data at the address to which the file was mapped. So, using pseudo-code to illustrate the way in which an existing program might be changed to use mmap(), the following:

fildes = open(...) lseek(fildes, some_offset) read(fildes, buf, len) /* use data in buf */

becomes:

fildes = open(...) address = mmap(0, len, PROT_READ, MAP_PRIVATE, fildes, some_offset) /* use data at address */

mmap HP-UX EXTENSIONS

NAME (HP-UX)

mmap - map pages of memory

SYNOPSIS (HP-UX)

#include <sys/mman.h> caddr_t mmap( caddr_t addr, size_t len, int prot, int flags, int fildes, off_t off);

DESCRIPTION

MAP_FILE

Create a mapped file region.

MAP_ANONYMOUS

Create an unnamed memory region.

MAP_VARIABLE

Place region at implementation-computed address.

MAP_NORESERVE

Lazily evaluate swap space reservation.

MAP_LOCAL

Allocate physical memory from the current locality domain.

MAP_IO

Map the physical IO space in user process address space.

The MAP_FILE and MAP_ANONYMOUS flags control whether the region to be mapped is a mapped file region or an anonymous shared memory region. Exactly one of these flags must be selected.

If MAP_FILE is set in flags:

  • A new mapped file region is created, mapping the file associated with fildes.

  • off specifies the file byte offset at which the mapping starts. This offset must be a multiple of the page size returned by sysconf(_SC_PAGE_SIZE).

  • If the end of the mapped file region is beyond the end of the file, any reference to an address in the mapped file region corresponding to an offset beyond the end of the file results in the delivery of a SIGBUS signal to the process, unless the address lies in the last partial page corresponding to the range beyond the end of the file. The last partial page mapping the range beyond the end of the file is always initialized to zeros, and any modified portions of the last page of a file which are beyond its end are not written back to the file.

If MAP_ANONYMOUS is set in flags:

  • A new memory region is created and initialized to all zeros. This memory region can be shared only with descendants of the current process.

  • If the fildes argument is not -1, an EINVAL error is generated.

  • The value of off is meaningless because there is no underlying file object for the memory region.

The MAP_VARIABLE and MAP_FIXED flags control the placement of the region as described below. Exactly one of these flags must be selected.

If MAP_VARIABLE is set in flags:

  • If the requested address is NULL, or if it is not possible for the system to place the region at the requested address, the region is placed at an address selected by the system. If the requested address is not a multiple of the page size returned by sysconf(_SC_PAGE_SIZE), the system treats the address as if it were rounded up to the next larger page size multiple.

If MAP_FIXED is set in flags:

  • addr must be a multiple of the page size returned by sysconf(_SC_PAGE_SIZE).

If MAP_NORESERVE is set in flags:

  • no swap space is initially be reserved for the private mapping. Without this flag, the creation of a MAP_PRIVATE region reserves swap space equal to the size of the mapping. When a page in the mapping is first modified (written into), a private page is created and the swap space which had been reserved is used to hold the private copy of the data in the event of a page-out. An initial write into a page of a MAP_NORESERVE mapping produces results which depend on the current availability of system swap space since the swap space reservation occurs at the time of the first write and only for the affected page. If the swap space reservation can be made for the page, the write succeeds and is processed as described above; if not, the write fails and a SIGBUS signal is posted to the writing process for the effective virtual address. madvise(...,MADV_DONTNEED) on a MAP_NORESERVE object will release swap space reservations for relevant pages.

If MAP_LOCAL is set in flags:

  • Memory for this region will be allocated from the current locality domain. This flag overrides the default allocation policy of first touch. Under a first touch allocation policy, when memory needs to be allocated, the locality domain chosen is that of the currently executing process.

If MAP_IO is set in flags :

  • No other flag can be specified in flags.

  • The off parameter specifies the start address as a page number of the physical IO address range to be mapped. The physical address must fall into the processor's noncoherent IO space. The 32-bit user process must specify 32-bit physical address only, whereas the 64-bit user process must specify 40-bit physical address.

  • The size parameter specifies the range of the IO space to be mapped in bytes. It must be multiple of pages. Also, the range should be such that it does not result in multiple noncontiguous virtual address mappings due to 32-bit/64-bit address space compatibility issues.

  • The specified physical IO address range is mapped in the user process address space at the virtual address determined by the HP-UX address space layout. The virtual address is returned to the caller on successful mapping.

  • The specified IO space range can be mapped only if it has no partial overlap with any other IO range currently mapped in any process. If the specified range is exactly same as one currently mapped, then the mapping succeeds. If the specified range has no overlap with any of existing mapped ranges, then also the mapping succeeds.

  • The user process can explicitly unmap the IO range from its address space by specifying to munmap(2) the virtual address returned by mmap().

  • The mapping of physical IO space is a privileged operation. The user process must have registered as a real time application (RTAPP) by calling rtctl(2) system call.

  • The user should look at the platform architecture for physical IO space layout to study which devices, controllers or registers are mapped at any IO address.

The prot argument can be PROT_NONE, or any combination of PROT_READ, PROT_WRITE, and PROT_EXEC OR'ed together. If PROT_NONE is not specified, the system may grant other access permissions to the region in addition to those explicitly requested, except that write access will not be granted unless PROT_WRITE is specified.

mmap() cannot create a mapped file region unless the file descriptor used to map the file is open for reading. For a mapped file region that is mapped with MAP_SHARED, mmap() grants write access permission only if the file descriptor is open for writing. If a region was mapped with either MAP_PRIVATE or MAP_ANONYMOUS, mmap() grants all requested access permissions.

After the successful completion of mmap(), fildes can be closed without effect on the mapped region or on the contents of the mapped file. Each mapped region creates a file reference, similar to an open file descriptor, that prevents the file data from being deallocated.

Whether modifications made to the file using write() are visible to mapped regions, and whether modifications to a mapped region are visible with read(), is undefined except for the effect of msync().

If an enforcement-mode file lock is in effect for any range of a file, a call to mmap() to map any range of the file with access rights that would violate the lock fails. The msem_lock() and msem_unlock() semaphore interfaces can be used to coordinate shared access to a region created with the MAP_SHARED flag. The advisory locks of the lockf() or fcntl() interfaces have no effect on memory mapped access, but they can be used to coordinate shared access to a MAP_SHARED mapped file region.

For a memory mapped file, the st_atime and st_mtime values returned by stat() are updated when a page in the memory mapped region is read from or written to the file system.

After a call to fork(), the child process inherits all mapped regions with the same data and the same sharing and protection attributes as in the parent process. Each mapped file and anonymous memory region created with mmap() is unmapped upon process exit, and by a successful call to any of the exec functions.

MAP_NORESERVE attribute is inherited across a fork() call; at the time of the fork(), swap space for a mapping is reserved in the child only for dirtied private pages that currently exist in the parent; thereafter the child's mapping reservation policy is as described above.

A SIGBUS signal is delivered to a process when a write reference to a mapped file region would cause a file system error condition such as exceeding quota or file system space limits.

A SIGBUS signal is delivered to a process upon a write reference to a region without PROT_WRITE protection, or any reference to a region with PROT_NONE protection.

A call to mmap() with PROT_EXECUTE specified, but without PROT_WRITE specified for a MAP_SHARED|MAP_FILE mapping is treated by the system as the execution of the underlying file. This implies that such a call fails if the file is currently open for writing or mapped with MAP_SHARED|PROT_WRITE options by any process, and that if the call succeeds, the file cannot be opened for writing or subsequently mapped with MAP_SHARED|PROT_WRITE options as long as such mappings are present. A file's status as an active executable file is determined only at the time of an exec(), exit(), or mmap() operation. mprotect() operations on a MAP_FILE|MAP_SHARED mapping have no effect on the underlying file's status as an active executable file.

ERRORS

[EACCES]

The file referred to by fildes is not open for read access, or the file is not open for write access and PROT_WRITE was set for a MAP_SHARED mapping operation, or PROT_EXECUTE was set for a MAP_SHARED mapping operation and the underlying file does not have execute permission.

[EOVERFLOW]

The file is a regular file and the value of off+len exceeds the offset maximum established in the open file description associated with fildes.

[ETXTBSY]

MAP_SHARED and MAP_FILE are set, and PROT_EXECUTE is set and PROT_WRITE is not set, and the file being mapped is currently open for writing.

[EINVAL]

The value of off+len exceeds the maximum supported offset for mapped files.

DEPENDENCIES

Series 700/800

Because the PA-RISC memory architecture utilizes a globally shared virtual address space between processes and discourages multiple virtual address translations to the same physical address, all concurrently existing MAP_SHARED mappings of a file range must share the same virtual address offsets and hardware translations. PA-RISC-based HP-UX systems allocate virtual address ranges for shared memory and shared mapped files in the range 0x80000000 through 0xefffffff for those applications compiled as 32-bit executables or for those 64-bit applications which specify MAP_SHARED and MAP_ADDR32 in the flags argument of the mmap() function. For applications compiled as 64-bit executables which specify MAP_SHARED and do not specify MAP_ADDR32, the shared mapped files are in the range 0x00000011 00000000 through 0x000003ff ffffffff and 0xc0000000 00000000 through 0xc00003ff ffffffff. These address ranges are used globally for all memory objects shared between processes.

This implies the following:

  • Any single range of a file cannot be mapped multiply into different virtual address ranges.

  • After the initial MAP_SHARED mmap() of a file range, all subsequent MAP_SHARED calls to mmap() to map the same range of a file must either specify MAP_VARIABLE in flags and inherit the virtual address range the system has chosen for this range, or specify MAP_FIXED with an addr that corresponds exactly to the address chosen by the system for the initial mapping. Only after all mappings for a file range have been destroyed can that range be mapped to a different virtual address.

  • In most cases, two separate calls to mmap() cannot map overlapping ranges in a file. The virtual address range reserved for a file range is determined at the time of the initial mapping of the file range into a process address space. The system allocates only the virtual address range necessary to represent the initial mapping. As long as the initial mapping exists, subsequent attempts to map a different file range that includes any portion of the initial range may fail with an ENOMEM error if an extended contiguous address range that preserves the mappings of the initial range cannot be allocated.

  • Separate calls to mmap() to map contiguous ranges of a file do not necessarily return contiguous virtual address ranges. The system may allocate virtual addresses for each call to mmap() on a first available basis.

  • The use of MAP_FIXED is strongly discouraged because it is not portable. Using MAP_FIXED is generally unsuccessful on this implementation, and when it is successful, it may prevent the system from optimally allocating virtual address space.

MAP_FIXED is discouraged, but there are some applications which by design must fix pointer offsets into file data. The application must map the file at a specific address in order for the file offsets embedded in the file to make sense.

Processes cannot control the usage of global virtual address space, but they can control what happens within their private data area. The Series 700/800 allows a single process to exclusively map a file MAP_SHARED into its private data space. When a process specifies MAP_SHARED and MAP_FIXED with a private data address (i.e. second quadrant for 32-bit executable, third quadrant for 64-bit executable), the kernel interprets this as an exclusive mapping of the file. The request will only succeed if no other processes in the system currently have that file mapped through MAP_SHARED. If the file is already mapped the caller receives an EBUSY error. If the call is successful, the calling process is the only process allowed to map that file using MAP_SHARED until it unmaps the file using munmap(). Because it is exclusive, the mmap() is not inherited across fork(). When a file is exclusively mapped only MAP_PRIVATE mappings are allowed by other processes.

The following combinations of protection modes are supported:

  • PROT_NONE

  • PROT_READ

  • PROT_READ|PROT_EXECUTE

  • PROT_READ|PROT_WRITE

  • PROT_READ|PROT_WRITE|PROT_EXECUTE

If a MAP_PRIVATE mapping is created of a file for which a MAP_SHARED mapping exists, a separate copy of a page for the MAP_PRIVATE mapping is created at the time of the first access to the page through the private mapping.

AUTHOR

mmap() was developed by HP, AT&T, and OSF.

STANDARDS CONFORMANCE

mmap(): AES, SVID3

© Hewlett-Packard Development Company, L.P.