Programming Interfaces Guide

Chapter 1 Memory Management

This chapter describes an application developer's view of virtual memory in SunOS.

Memory Management Interfaces

Applications use the virtual memory facilities through several sets of interfaces. This section summarizes these interfaces. This section also provides examples of the interfaces' use.

Creating and Using Mappings

mmap(2) establishes a mapping of a named file system object into a process address space. A named file system object can also be partially mapped 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. You must specify a mapping type. If the MAP_SHARED flag is set, write operations modify the mapped object. No further operations on the object are needed to make the change. If the MAP_PRIVATE flag is set, the first write operation to the mapped area creates a copy of the page. All further write operations reference the copy. Only modified pages are copied.

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

After you have established the mapping through mmap(2), the file descriptor used in the call is no longer used. If you close the file, the mapping remains until munmap(2) undoes the mapping. Creating a new mapping replaces an existing mapping.

A mapped file can be shortened by a call to truncate. An attempt to access 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. The size of the block is 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. The block's address is chosen by the system.

removed to fr.ch4/pl1.create.mapping.c

Some devices or files are useful only when accessed by mapping. Frame buffer devices used to support bit-mapped displays are an example of this phenomenon. Display management algorithms are much simpler to implement when the algorithms operate directly on the addresses of the display.

Removing Mappings

munmap(2) removes all mappings of pages in the specified address range of the calling process. munmap(2) has no affect on the objects that were mapped.

Cache Control

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.

Using mincore

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 the page but before mincore returns the data, returned information can be outdated. Only locked pages are guaranteed to remain in memory.

Using 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 process or in other processes do not result in page faults that require an I/O operation. Because this I/O operation interferes with normal operation of virtual memory, as well as slowing other processes, the use of mlock is limited to the superuser. The limit to the number of pages that can be locked in memory is dependent on system configuration. 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 that is 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. For a discussion of this redirection, see Creating and Using Mappings.

Using mlockall and munlockall

mlockall(3C) and munlockall(3C) are similar to mlock and munlock, but mlockall and munlockall 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.

Using msync

msync(3C) causes all modified pages in the specified address range to be flushed to the objects mapped by those addresses. This command is similar to fsync(3C), which operates on files.

Library-Level Dynamic Memory

Library-level dynamic memory allocation provides an easy-to-use interface to dynamic memory allocation.

Dynamic Memory Allocation

The most often used interfaces are:

Other dynamic memory allocation interfaces are memalign(3C), valloc(3C), and realloc(3C)

Dynamic Memory Debugging

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 that are 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, particularly errors that are read from uninitialized memory. For this reason, certain errors are suppressed if no symbolic information is available. These errors are rui for a.out and rui + aib + air for shared libraries. This behavior can be changed by using suppress and unsuppress.

check -access

The -access option turns on access checking. RTC reports the following errors:

baf

Bad free

duf

Duplicate free

maf

Misaligned free

mar

Misaligned read

maw

Misaligned write

oom

Out of memory

rua

Read from unallocated memory

rui

Read from uninitialized memory

rwo

Write to read-only memory

wua

Write to unallocated memory

The default behavior is to stop the process after detecting each access error. This behavior 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 the error happens. Change this behavior using the rtc_auto_suppress dbxenv variable. The default setting of this variable is on.

check -leaks [-frames n] [-match m]

The -leaks option turns on leak checking. RTC reports the following errors:

aib

Possible memory leak – The only pointer points in the middle of the block

air

Possible memory leak – The pointer to the block exists only in register

mel

Memory leak – No pointers to the block

With leak checking turned on, you get an automatic leak report when the program exits. All leaks, including potential leaks, are reported at that time. By default, a non-verbose report is generated. This default is controlled by the dbxenv rtc_mel_at_exit. However, you can ask for a leak report at any time.

The -frames n variable displays up to n distinct stack frames when reporting leaks. The -match m variable combines leaks. If the call stack at the time of allocation for two or more leaks matches m frames, these leaks are reported in a single combined leak report. The default value of n is the larger of 8 or the value of m. The maximum value of n is 16. The default value of m is 2.

check -memuse [-frames n] [-match m]

The -memuse option turns on memory use (memuse) checking. Using check -memuse implies using check -leaks. In addition to a leak report at program exit, you also get a report listing blocks in use, biu. By default, a non-verbose report on blocks in use is generated. This default is controlled by the dbxenv rtc_biu_at_exit. At any time during program execution, you can see where the memory in your program has been allocated.

The -frames n and -match m variables function as described in the following section.

check -all [-frames n] [-match m]

Equivalent to check -access; check -memuse [-frames n] [-match m]. The value of rtc_biu_at_exit dbxenv variable is not changed with check -all. So, by default, no memory use report is generated at exit.

check [funcs] [files] [loadobjects]

Equivalent to check -all; suppress all; unsuppress all in funcs files loadobjects. You can use this option to focus RTC on places of interest.

Other Memory Control Interfaces

This section discusses additional memory control interfaces.

Using sysconf

sysconf(3C) returns the system dependent size of a memory page. For portability, applications should not embed any constants that specify the size of a page. Note that varying page sizes are not unusual, even among implementations of the same instruction set.

Using mprotect

mprotect(2) assigns the specified protection to all pages in the specified address range. The protection cannot exceed the permissions that are allowed on the underlying object.

Using brk and sbrk

A break is the greatest valid data address in the process image that is not in the stack. When a program starts executing, the break value is normally set by execve(2) to the greatest address defined by the program and its data storage.

Use brk(2) to set the break to a greater address. You can also use sbrk(2) to add an increment of storage to the data segment of a process. You can get the maximum possible size of the data segment by a call to getrlimit(2).

caddr_t
 brk(caddr_t addr);

 caddr_t
 sbrk(intptr_t incr); 

brk identifies the lowest data segment location not used by the caller as addr. This location is rounded up to the next multiple of the system page size.

sbrk, the alternate interface, adds incr bytes to the caller data space and returns a pointer to the start of the new data area.