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)