Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

csync(2)

getrlimit(2)

memcntl(2)

mprotect(2)

munmap(2)

sysconf(2)

msync(3C)



mmap(2)                        DG/UX R4.11MU05                       mmap(2)


NAME
       mmap - map pages of memory

SYNOPSIS
       #include <sys/types.h>
       #include <sys/mman.h>

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

DESCRIPTION
       The mmap(2) call maps a memory object into the caller's address
       space, based on the supplied parameters:

       addr           is the optional starting address for the new memory
                      region to map.

       len            is the length in bytes of the region to map.

       prot           assigns the access attribute for the mapped region:
                      read, write, execute, a combination, or no access.

       flags          specify the mapping mode (shared or private), and
                      whether the requested address must be used exactly.

       fd             is the file descriptor of the memory object to be
                      mapped into the region.

       off            is the offset into the file to be mapped into the
                      region.

       The format of the call is:

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

       The file fd, starting at offset off, is mapped into the caller's
       address space. The mapping begins at address pa and extends for len
       bytes. Argument prot specifies how the region may be accessed, and
       flags whether changes to the file should be shared with other
       processes (and other attributes).

       Once a file is mapped, a process may access it using the mapped
       address instead of the read/write interface. Consider the following
       pseudo-code, where off is assumed to be page aligned:

                fd = open(...);
                lseek(fd, off, SEEK_SET);
                read(fd, buf, len);
                /* use data in buf */

             Here is a rewrite using mmap(2):

                fd = open(...);
                pa = mmap((void *) 0, len, (PROT_READ | PROT_WRITE),
                             MAP_PRIVATE, fd, off);
                /* use data at address pa */

       The descriptor fd may designate a device--a block or character
       special file. If it does, the off and len parameters are usually
       checked to ensure that the entire range of addresses returned can be
       accessed at all times. If all cannot, the call fails and sets errno
       values that can only occur with special files. More commonly, fd
       designates a regular file. In this case, no check is done. The call
       will succeed even if len exceeds the size of the mapped file, for
       reasons explained below.  If you use mmap(2) to map special files,
       consult the appropriate documentation for device-specific
       restrictions which may apply.

   Maps and Page Boundaries
       The system maps on page boundaries, but there is no requirement that
       the size of a file mapped by this call will be a multiple of the
       system page size.  The off value must be an integer multiple of the
       system page size, but len need not be.  The following paragraphs draw
       out some possible consequences of these facts that may not be
       obvious.

       To get the system page size, invoke sysconf(2) with the _SC_PAGESIZE
       parameter.

       Three values determine the exact range of addresses that user
       processes will be able to access via mmap(2): the two parameters len
       and off, and the size of the file fd.  The size of the file, called
       simply size here, is the value stored in the st_size field of the
       stat structure; see stat(2).

       The address range [pa, pa + len - 1] may be accessible to user
       processes after a successful call to mmap(2).  There are several
       cases to consider.  First assume that off is zero.  If len is less
       than or equal to size, then all addresses in the address range will
       be valid.  In fact, the entire page containing the last byte in the
       address range will be valid; this occurs because the system can map
       areas only in increments of one system page.

       If len is greater than size, then the range [pa, pa + size - 1] will
       be valid and accessible, as well as any remainder of the last page in
       that range.  The address range beginning at the next page greater
       than pa + size, through the end of the page containing pa + len - 1,
       will be mapped, but accessing any address in this range will cause
       the signal SIGBUS to be delivered.  However, if another process
       extends the file while it is still mapped by the current process,
       then any pages in [pa, pa + len - 1] which overlap [pa + old_size, pa
       + new_size - 1] will become accessible by the mapping process.
       Likewise, any file truncation by another process may result in access
       faults in [pa, pa + len - 1] if the updated size is made smaller than
       len.

       The point is that, while mmap(2) will return an address range which
       is valid for the user process, accessing addresses in the range may
       fail.  A valid range does not mean that all address in the range can
       be read and written at all times.  The range is valid because it is a
       reserved part of the process's address space and meets the address
       space layout requirements.  Whether or not particular addresses can
       be accessed is solely dependent on the structure of the underlying
       file at the time of the memory access.  For example, touching an
       address may succeed now, but fail later because the file was
       truncated before the second memory reference.

       A special case worth noting occurs in the page which contains the
       last byte of the mapped file, and when the file size is not an
       integral multiple of the system page size.  Upon the first access to
       any address in the last page of the file, the entire page will be
       read from the file into memory, and the region from the last byte of
       the file to the end of the page will be filled with zeros.  Now, as
       stated above, the calling process may read or modify any data in the
       entire page.  However, when data is stored in the zero-filled region
       beyond the end of the file, it is not guaranteed to be available
       later.  Due to memory demands made by other processes in the system,
       that page may be written to backing store, but only data up to the
       current end of file will be written.  So, when it is retrieved later,
       only the data contained in the file will be read, with the rest of
       the page being zero-filled.  Hence any data written beyond the end of
       the file is lost.

       Now assume that a non-zero value for the off parameter is specified.
       (Recall that off must be an integral multiple of the system page
       size.)  If off + len is less than size, then [pa, pa + len - 1] is a
       valid address range, mapping bytes in the file specified by [off, off
       + len - 1].  As above, if len is not a multiple of the system page
       size, then the remainder of the last page in the range will also be
       mapped.  If off exceeds size, then the entire range [pa, pa + len -
       1] will not be accessible to the user process.  If size is greater
       than off, but off + len exceeds size, and if SIZE is shorthand for
       size rounded up the next page aligned value, then [pa, pa + SIZE -
       off - 1] will be accessible, but [pa + SIZE - off, pa + len - 1] will
       not.  As before, the accessibility of the address range is constant
       until the size of the mapped file is changed.  Recall that other
       processes may modify the size of the file.  Until an address is
       accessed, it cannot be determined whether accesses in the range will
       succeed or result in access faults and the delivery of SIGBUS.

       Finally, note that mmap(2) cannot increase the size of a file.  While
       a successful call may specify a len larger than the size of the file,
       only the file system calls, write(2) for example, will actually cause
       the file to expand.  No more than size bytes will ever be written
       back to the file.

   Shared, Private, and Fixed Maps
       The flags, defined in <sys/mman.h>, are:

       MAP_SHARED   Share memory modifications.

       MAP_PRIVATE  Memory modifications are private.

       MAP_FIXED    Use addr as the mapping start address.

       For a successful map, either MAP_SHARED or MAP_PRIVATE must be
       specified, but not both.

       MAP_SHARED and MAP_PRIVATE describe the disposition of write
       references to the memory object.  If MAP_SHARED is specified, write
       references will change the mapped file directly.  These changes
       appear immediately; that is, any other process which accesses the
       file will see the new data.  The file object is changed right away,
       but a delay will occur in writing data to the backing storage.  (Note
       that a system configuration parameter exists to specify the maximum
       amount of time that may pass before a file modification is recorded
       on backing storage.)

       If MAP_PRIVATE is specified, the initial write reference will create
       a private copy of the memory object page and redirect the mapping to
       the copy.  No changes to the private copy of the mapped address range
       will be written to the file referred to by fd.  Note that the private
       copy is not created until the first write; until then, other users
       who have the object mapped MAP_SHARED can change the object, and such
       changes will be be seen by the process which has the MAP_PRIVATE
       mapping.  Once a private copy of a file page has been made,
       subsequent modification to the file page will not be reflected in the
       private copy.

       The mapping type is retained across a fork(2).

       MAP_FIXED informs the system that the value of pa must be addr,
       exactly.  When this option is specified, addr must be a page aligned
       address.  The use of MAP_FIXED may prevent an implementation from
       making the most effective use of system resources.  Thus, the use of
       this option is discouraged, except to deliberately replace previous
       mappings.

       When MAP_FIXED is specified, an implicit munmap(2) operation is
       performed on the address range [addr, addr + len - 1].  See munmap(2)
       for further details.

       When MAP_FIXED is not specified, the system uses addr in an
       implementation-defined manner to arrive at pa.  Currently, the system
       ignores addr completely unless MAP_FIXED is set.  The pa so chosen
       will be an area of the address space which the system deems suitable
       for a mapping of len bytes to the specified object.  An addr value of
       (void *) 0 grants the system complete freedom in selecting pa,
       subject to the following constraints:  address (void *) 0 will never
       be used, nor will the system replace any extant mapping, nor map into
       areas considered part of the potential data or stack segments.  A
       value of addr other than (void *) 0 is discouraged when MAP_FIXED is
       not set.

       Some implementations add paddings of invalid ranges equivalent to the
       size of one system page around the mapped region when MAP_FIXED is
       not specified.  So, if PAGE is equal to the system page size, and LEN
       is the next page aligned value greater than len, then the address
       ranges [pa - PAGE, pa - 1] and [pa + LEN, pa + LEN + PAGE - 1] will
       both be invalid.  Such invalid address regions around the mapping are
       provided to aid in the debugging of user processes with stray memory
       references.  One consequence of this is that use of MAP_FIXED is
       required to get successive regions mapped at contiguous addresses
       within a portable application.

   Memory Access Options
       The parameter prot determines whether read, write, execute, or some
       combination of accesses are requested for the pages being mapped.
       Any of these values may be be ORed together, but not all combinations
       are useful.  The protection options are:

       PROT_READ    The memory can be read.

       PROT_WRITE   The memory can be written.

       PROT_EXEC    The memory can be executed.

       PROT_NONE    The memory cannot be accessed.

       Not all implementations literally provide all possible combinations.
       PROT_WRITE is often implemented as PROT_READ | PROT_WRITE and
       PROT_EXEC as PROT_READ | PROT_EXEC.  However, no implementation will
       permit a write to succeed where PROT_WRITE has not been set.  Also,
       no implementation will permit any access to succeed where PROT_NONE
       (alone) has been set.

       On 88K systems such as the AViiON, programs that modify and execute
       memory need to invoke csync(2) just after the modification and prior
       to the execution.  Doing so notifies the system, and synchronizes the
       contents of memory with that of the caches.

       When several processes share a memory region, note:

       ·    Executable mappings of the shared region should include write
            access, to insure that reading is always safe.

       ·    At least one of the processes must invoke csync(2), following
            any modifications by the processes, and preceding execution by
            any of them.

       Note that an mmap(2) call may fail and leave the user's address space
       in an unknown state.  If mmap(2) is called with MAP_FIXED, with addr
       and len parameters that overlap a previously mapped region, the
       implicit unmapping may succeed, but the new mapping operation may
       fail.

ACCESS CONTROL
       The file descriptor fd must be open with at least read intent.

       If MAP_SHARED is specified, the file referenced by fd cannot be
       mapped with PROT_WRITE permission unless the file was opened O_RDWR.
       Also, any attempt to write into the address range returned by an
       mmap(2) call which did not specify PROT_WRITE will cause a SIGSEGV to
       be delivered, regardless of the type of mapping.

RETURN VALUE
       On success, mmap(2) returns the starting address of the new mapping.
       On failure it returns (void *) -1 and sets errno to indicate an
       error.

DIAGNOSTICS
       Under the following conditions, mmap(2) fails and sets errno to:

       EINVAL         if the off parameter is negative.

       EINVAL         if the quantity off + len is greater than SIZE_T_MAX.

       EINVAL         if the off parameter is not an integral multiple of
                      the system page size.

       EINVAL         if the argument addr is not a page aligned address and
                      MAP_FIXED is specified.

       EINVAL         if addr + len exceeds the largest legal user address
                      and MAP_FIXED is specified.

       EINVAL         if the argument flags does not contain either
                      MAP_PRIVATE or MAP_SHARED.

       EINVAL         if mapping was attempted on fd that was not a regular
                      file or device.

       ENOSYS         if mapping was attempted on a file system which does
                      not support mapping.

       ENODEV         if fd refers to a device for which mmap() is
                      unsupported.

       ENXIO          if [off, off + len - 1] is not a legal range to be
                      mapped as defined by that particular device.  This
                      error applies only to character special and block
                      special files.

       EIO            if fd refers to an NFS file, and record locks are held
                      on the file.

       EAGAIN         if fd refers to a regular file and mandatory file
                      locking is in effect for the file.

       EAGAIN         if the address range could not be locked into memory.
                      This might happen due to a previous call to memcntl(2)
                      which set the MCL_FUTURE option on the process's
                      address space.

       EAGAIN         if the mapping uses /dev/zero or MAP_PRIVATE is
                      specified in conjunction with PROT_WRITE, and would
                      reserve more space than the available physical memory
                      and swap space.

       EBADF          if fd is not a valid, active descriptor.

       EACCES         if fd is not open for read, regardless of the
                      protection specified, or fd is not open for write and
                      PROT_WRITE was specified for a MAP_SHARED mapping.

       ENOMEM         if the argument len is zero.

       ENOMEM         if adding the size of the mapped range would exceed
                      the limit value RLIMIT_AS for the process.

       ENOMEM         if MAP_FIXED was specified and the range [addr, addr +
                      len] exceeds that allowed for the address space of a
                      process, or MAP_FIXED was not specified and there is
                      insufficient room in the address space to effect the
                      mapping.

SEE ALSO
       csync(2), getrlimit(2), memcntl(2), mprotect(2), munmap(2),
       sysconf(2), msync(3C).


Licensed material--property of copyright holder(s)

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026