This chapter describes an application developer's view of virtual memory in SunOS.
"Memory Management Interfaces" describes interfaces and cache control.
Library level dynamic memory allocation and debugging are described in "Library-Level Dynamic Memory".
"Other Memory Control Interfaces " describes other memory control interfaces.
Memory Management Interfaces
Creating and Using Mappings
mmap(2) establishes a mapping of a named file system object (or part of one) into a process address space. This basic memory management interface is very simple. Use open(2) to open the file, then use mmap(2) to create the mapping with appropriate access and sharing options. Then proceed with your application.
The mapping established by mmap(2) replaces any previous mappings for the specified address range.
The flags MAP_SHARED and MAP_PRIVATE specify the type of mapping and you must specify one of them. MAP_SHARED specifies that writes modify the mapped object. No further operations on the object are needed to make the change. MAP_PRIVATE specifies that an initial write to the mapped area creates a copy of the page and all further writes reference the copy. Only modified pages are copied.
A mapping type is retained across a fork(2).
Once you have established the mapping through mmap(2), there is no further use for the file descriptor used in the call. If you close the file, the mapping remains until munmap(2) undoes the mapping or a new mapping replaces it.
If a mapped file is shortened by a call to truncate, an access to the area of the file that no longer exists causes a SIGBUS signal.
Mapping /dev/zero gives the calling program a block of zero-filled virtual memory of the size specified in the call to mmap(2). The following code fragment demonstrates a use of this technique to create a block of zeroed storage in a program, at an address that the system chooses.
removed to fr.ch4/pl1.create.mapping.c
Some devices or files are useful only when accessed by mapping. An example of this is frame buffer devices used to support bit-mapped displays. Display management algorithms are much simpler to implement when they operate directly on the addresses of the display.
The virtual memory system in SunOS is a cache system, in which processor memory buffers data from file system objects. Interfaces are provided to control or interrogate the status of the cache.
The mincore(2) interface determines the residency of the memory pages in the address space covered by mappings in the specified range. Because the status of a page can change after mincore checks it but before mincore returns the data, returned information can be outdated. Only locked pages are guaranteed to remain in memory.
mlock and munlock
mlock(3C) causes the pages in the specified address range to be locked in physical memory. References to locked pages (in this or other processes) do not result in page faults that require an I/O operation. This operation interferes with normal operation of virtual memory and slows other processes, so use of mlock is limited to the superuser. There is a limit (dependent on system configuration) to the number of pages that can be locked in memory. The call to mlock fails if this limit is exceeded.
munlock releases the locks on physical pages. If multiple mlock calls are made on an address range of a single mapping, a single munlock call releases the locks. However, if different mappings to the same pages are locked by mlock, the pages are not unlocked until the locks on all the mappings are released.
Removing a mapping also releases locks, either through being replaced with an mmap(2) operation or removed with munmap(2).
The copy-on-write event associated with a MAP_PRIVATE mapping transfers a lock on the source page to the destination page. Thus locks on an address range that includes MAP_PRIVATE mappings are retained transparently along with the copy-on-write redirection (see "Creating and Using Mappings" for a discussion of this redirection).
mlockall and munlockall
mlockall(3C) and munlockall(3C) are similar to mlock and munlock, but they operate on entire address spaces. mlockall sets locks on all pages in the address space and munlockall removes all locks on all pages in the address space, whether established by mlock or mlockall.
Library-Level Dynamic Memory
Library-level dynamic memory allocation provides an easy-to-use interface to dynamic memory allocation.
The most often used interfaces are malloc(3C), free(3C), calloc(3C), and cfree(3MALLOC). Other dynamic memory allocation interfaces are memalign(3C), valloc(3C), and realloc(3C)
free returns the memory obtained from malloc, calloc, realloc, memalign, or valloc to system memory. Trying to free a block that was not reserved by a dynamic memory allocation interface is an error that can cause a process to crash.
calloc returns a pointer to a block of memory that is initialized to all zeros. Memory reserved by calloc can be returned to the system through either cfree or free. The memory is allocated and aligned to contain an array of a specified number of elements of a specified size.
realloc changes the size of the memory block allocated to a process. realloc can be used to increase or reduce the size of an allocated block of memory and is the only way to shrink a memory allocation without causing a problem. The location in memory of the reallocated block may be changed, but the contents will be unchanged up to the point of the allocation size change.
The Sun WorkShop package of tools is useful in finding and eliminating errors in dynamic memory use. The Run Time Checking (RTC) facility of the Sun WorkShop uses the functions described in this section to find errors in dynamic memory use.
RTC does not require the program be compiled using -g in order to find all errors. However, symbolic (-g) information is sometimes needed to guarantee the correctness of certain errors (mostly read from uninitialized memory). For this reason, certain errors (rui for a.out and rui + aib + air for shared libraries) are suppressed if no symbolic information is available. This behavior can be changed by using suppress and unsuppress.
The -access option turns on access checking. RTC reports the following errors:
Out of memory
Read from unallocated memory
Read from uninitialized memory
Write to read-only memory
Write to unallocated memory
The default behavior is to stop the process after detecting each access error. This can be changed using the rtc_auto_continue dbxenv variable. When set to on, RTC logs access errors to a file. The file name is determined by the value of the rtc_error_log_file_name dbxenv variable. By default, each unique access error is only reported the first time it happens. Change this behavior using the rtc_auto_suppress dbxenv variable. The default setting of this variable is on.