Process management

Creating and using mappings

mmap(caddr_t addr, size_t len, int prot, int flags, int fd, off_t off);
mmap establishes a mapping between a process's address space and an object in the system's virtual memory. All other system functions that contribute to the definition of an address space are built from mmap, the system's most fundamental function for defining the contents of an address space. The format of an mmap call is:
paddr = mmap(addr, len, prot, flags, fd, off);
mmap establishes a mapping from the process's address space at an address paddr for len bytes to the object specified by fd at offset off for len bytes. A successful call to mmap returns paddr as its result, which is an implementation-dependent function of the parameter addr and the setting of the MAP_FIXED bit of flags, as described below. The address range [paddr, paddr + len) must be valid for the address space of the process and the range [off, off + len) must be valid for the virtual memory object. (The notation [start, end) denotes the interval from start to end, including start but excluding end.)

NOTE: The mapping established by mmap replaces any previous mappings for the process's pages in the range [paddr, paddr + len).

The parameter prot determines whether read, execute, write or some combination of accesses are permitted to the pages being mapped. To deny all access, set prot to PROT_NONE. Otherwise, specify permissions by an OR of PROT_READ, PROT_EXECUTE, and PROT_WRITE.

A write access must fail if PROT_WRITE has not been set, though the behavior of the write can be influenced by setting MAP_PRIVATE in the flags parameter, which provides other information about the handling of mapped pages, as described below:

The file descriptor used in a mmap call need not be kept open after the mapping is established. If it is closed, the mapping will remain until such time as it is replaced by another call to mmap that explicitly specifies the addresses occupied by this mapping; or until the mapping is removed either by process termination or a call to munmap. Although the mapping endures independent of the existence of a file descriptor, changes to the file can influence accesses to the mapped area, even if they do not affect the mapping itself. For instance, should a file be shortened by a call to truncate, such that the mapping now ``overhangs'' the end of the file, then accesses to that area of the file which ``does not exist'' will result in SIGBUS signals. It is possible to create the mapping in the first place such that it ``overhangs'' the end of the file -- the only requirement when creating a mapping is that the addresses, lengths, and offsets specified in the operation be possible (that is, within the range permitted for the object in question), not that they exist at the time the mapping is created (or subsequently.)

Similarly, if a program accesses an address in a manner inconsistently with how it has been mapped (for instance, by attempting a store operation into a mapping that was established with only PROT_READ access), then a SIGSEGV signal will
result. SIGSEGV signals will also result on any attempt to reference an address not defined by any mapping.

In general, if a program makes a reference to an address that is inconsistent with the mapping (or lack of a mapping) established at that address, the system will respond with a SIGSEGV violation. However, if a program makes a reference to an address consistent with how the address is mapped, but that address does not evaluate at the time of the access to allocated storage in the object being mapped, then the system will respond with a SIGBUS violation. In this manner a program (or user) can distinguish between whether it is the mapping or the object that is inconsistent with the access, and take appropriate remedial action.

Using mmap to access system memory objects can simplify programs in a variety of ways. Keeping in mind that mmap can really be viewed as just a means to access memory objects, it is possible to program using mmap in many cases where you might program with read or write. However, it is important to realize that mmap can only be used to gain access to memory objects -- those objects that can be thought of as randomly accessible storage. Thus, terminals and network connections cannot be accessed with mmap because they are not ``memory.'' Magnetic tapes, even though they are memory devices, can not be accessed with mmap because storage locations on the tape can only be addressed sequentially. Some examples of situations which can be thought of as candidates for use of mmap over more traditional methods of file access include:

The remainder of this section will illustrate some other concepts surrounding mapping creation and use.

Mapping /dev/zero gives the calling program a block of zero-filled virtual memory of the size specified in the call to mmap. /dev/zero is a special device, that responds to read as an infinite source of bytes with the value 0, but when mapped creates an unnamed object to back the mapped region of memory. The following code fragment demonstrates a use of this to create a block of scratch storage in a program, at an address of the system's choosing.

 * Function to allocate a block of zeroed storage.  Parameter
 * is the number of bytes desired.  The storage is mapped as
 * MAP_SHARED, so that if a fork occurs, the child process
 * will be able to access and modify the storage.  If we wished
 * to cause the child's modifications (as well as those by the
 * parent) to be invisible to the ancestry of processes, we
 * would use MAP_PRIVATE.
get_zero_storage(int len);
	int fd;
	caddr_t result;

if ((fd = open("/dev/zero", O_RDWR)) == -1) return ((caddr_t)-1); result = mmap(0, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); (void) close(fd); return (result); }

As written, this function permits a hierarchy of processes to use the area of allocated storage as a region of communication (for implicit interprocess communication purposes). Later in this section we will describe a set of system facilities that provide a similar function packaged for accomplishing the same purpose without requiring that the processes be in a parent-child hierarchy.

In some cases, devices or files are only useful if accessed via mapping. An example of this is frame buffer devices used to support bit-mapped displays, where display management algorithms function best if they can operate randomly on the addresses of the display directly.

Finally, it is important to remember that mappings can be operated upon at the granularity of a single page. Even though a mapping operation may define multiple pages of an address space, there is no restriction that subsequent operations on those addresses must operate on the same number of pages. For instance, an mmap operation defining ten pages of an address space may be followed by subsequent munmap (see below) operations that remove every other page from the address space, leaving five mapped pages each followed by an unmapped page. Those unmapped pages may subsequently be mapped to different locations in the same or different objects, or the whole range of pages (or any partition, superset, or subset of the pages) used in other mmap or other memory management operations. Further, it must be noted that any mapping operation that operates on more than a single page can ``partially succeed'' in that some parts of the address range can be affected even though the call returns a failure. Thus, an mmap operation that replaces another mapping, if it fails, may have deleted the previous mapping and failed to replace it. Similarly, other operations (unless specifically stated otherwise) may process some pages in the range successfully before operating on a page where the operation fails.

Not all device drivers support memory mapping. mmap fails if you try to map a device that does not support mapping.

Next topic: Removing mappings
Previous topic: Memory management interfaces

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004