SunSolve Internal

Infodoc ID   Synopsis   Date
13413   How is a User Process Defined in Memory?   24 Apr 1996

Description Top

In simplified terms, a process' address space is made up of both kernel & 
user space.
 
 The user space is then broken down into:
 
 1) program instructions.
 2) initialized data
 3) uninitialized data.
 4) stack.
 5) The unused space in between the stack & the uninitialized data
    which shrinks as the stack grows and/or uninitialized data becomes
    initialized.
 

From the kernel point of view, it gets a little more complex.  The
address space is broken into pages (4 or 8k, depending on architecture)
at the lowest level.  Pages are then grouped into segments.  A segment
is a contiguous number of pages that share an "identity".

What is an "identity"?  There are different kinds of segments, the most
common of which is a "segvn", a segment tied to a vnode (i.e. a file).
Segvn's are tied to a specific vnode and offset into that vnode.
Therefore, a contiguous span of pages that all belong to one vnode, and
are contiguous in that vnode, constitutes a single segment.  Segvns also
have a feature that individual pages of the segment may be remapped to
"anonymous" memory (i.e. swap space).

Pages have two other properties to note:  read-only (RO) vs.  read-write
(RW) (which is self-explanatory) and shared vs.  private.  For a shared
page, modifications made to the page are written back to the vnode the
page came from, thus modifying the file.  For a private page, the first
modification to the page causes the page to be remapped to an anonymous
page (swap), then the write happens.  This preserves the original
contents of the file.  This process is commonly called "copy-on-write".

An old 4.x a.out executable has 2 segments, program (text) and
initialized data.  It also gives the size of the uninitialized data.  When
it loads, the kernel sets up the text segment to point at the text pages
of the executable with shared RO permission.  The next segment created
is mapped private RW to the initialized data portion of the file.  The
uninitialized data is given a private RW segment already mapped to 
anonymous memory (that will be zero'ed out when accessed).  A stack
segment is created very similarly, except that this segment is created
at the top of the user's address space.

An ELF executable is much more complicated.  It can define any
number of segments, not just 3.  Furthermore, it directly supports the
runtime linker (ld.so), so that by the time the executable is actually
started, the ld.so and its own data segments are mapped in too.

Also, while any executable is running, it will likely map in files
(like shared object libraries (libc.so)).  These mappings get placed
just below the maximum size stack the process could have (based on 
the stacksize rlimit), thus filling in the "hole" between the stack
and the top of uninitialized data.

Resident Set Size, RSS in the /usr/ucb/ps output, is calculated by
looking at each page of the process's address space, and if that page
has a "hardware translation" to memory, it is counted.  This is a fancy
way of saying "if any page of the process is in RAM" it will be counted.
However, it is only an estimate, because there are cases that can both
under- and over-count pages, and things can also be changing faster than
you snapshot it.

Unused space (5) is not counted towards the address space (SIZE in the
/usr/ucb/ps output), everything else is (including things that are
mapped into the address space into the area originally called (5), like
libraries, shared memory segments, etc.)

Shared memory segments are their own segments, created using either 
mmap() or shmat().  As such, they usually get created at the top of the
gap called (5).

Technically, any page of memory can be shared if you give it the right
permissions (shared RW).
Product Area Kernel
Product Config
OS Solaris 2.x
Hardware any

Top

SunWeb Home SunWeb Search SunSolve Home Simple Search

Sun Proprietary/Confidential: Internal Use Only
Feedback to SunSolve Team