System Architecture

(INFT12-212 and 72-212)
Lab Notes for Week 9: Linux Memory Management System Calls

1  Introduction

2  Using ps to See Memory Allocation

In the first lab you saw that ps could give you details of all of the processes running on the Unix machine. After connecting to a different Linux box with SSH, run the following ps command:
    $ ps -o user,vsz,rss,pmem,fname -e | less

What does the -e option to ps mean? The columns that you see for each process are:
user:
The user who started the process running.
vsz:
The total size of the process in (virtual) memory in kilobytes as a decimal integer.
rss:
The resident set size of the process, in kilobytes as a decimal integer.
pmem:
The ratio of the process's resident set size to the physical memory on the machine, expressed as a percentage.
fname:
The first few character's of the process' name.
Explain the concept of the resident set. Explain why the resident set size is smaller than the total process size. Where is the rest of each process' memory?
One reason why the resident set is smaller than the process size is that Unix processes use shared libraries, similar to DLLs on Windows systems. The operating system doesn't include the size of any shared libraries in the resident set, because the libraries are loaded into memory only once.

3  Using df to See Swap Usage

With a paging virtual memory system using LRU, those least recently used pages are copied out to disk until they are required again (if ever). To see the amount of swap space in use, use the command:
    $ cat /proc/swaps

Remember that if the swap space is too small, then there is not enough room to keep the unused pages, and thrashing is likely to occur. On the other hand, if the swap space is too large, you waste disk space as the swap space cannot be used to store files.

4  Monitoring Paging Activity

The vmstat program is the best utility to monitor paging activity. As with the other xxxstat programs,
    $ vmstat 2 40

will give 40 vmstat reports, one every 2 seconds, and the first report is an average since the system was started. Read the manual on vmstat to see what information it provides. The main memory stats columns are:
swpd:
the amount of virtual memory used.
free:
the amount of idle memory.
buff:
the amount of memory used as buffers.
cache:
the amount of memory used as cache.
inact:
the amount of inactive memory. (-a option)
active:
the amount of active memory. (-a option)
si:
Amount of memory swapped in from disk (/s).
so:
Amount of memory swapped to disk (/s).
bi:
Blocks received from a block device (blocks/s).
bo:
Blocks sent to a block device (blocks/s).
in:
The number of interrupts per second, including the clock.
cs:
The number of context switches per second.
Watch the memory subsystem activity on the Linux box for a bit. Is it a problem if the available free memory goes down to nearly zero? Explain.
The swapped out column is often zero. Therefore, there must be many pages in memory which are unused but are not paged out to disk. Why are these unused pages not paged out?
Explain why there are page ins when there is ample free memory?

On my Linux box, while vmstat is running, I'll launch this program which simply tries to consume as much memory as possible and then touch all of the pages to makes its working set as big as possible.
Watch the results displayed by vmstat! Compare the amount of free physical memory before the thrashing process runs and afterwards. Explain why there is such a difference.
Another program to play with is eatmem.c which consumes memory without doing anything with it, so its working set stays small.

5  Components of a Process

A Unix process has several memory components: Which of these sections need to be stored as the program image on disk? Which don't? Why not?
The size program shows the sizes of the text, data and bss sections in a program's disk image. For example:
    $ which ls                          # Where on disk is ls kept?
      /bin/ls
    $ size /bin/ls 
    text    data     bss     dec     hex filename
   72778     856     944   74578   12352 /bin/ls

Find the size of the bash program on disk. Now use ps to see how much memory bash actually requires. Why does a bash process use much more memory then is in the disk image? Try this out for other Unix programs.

6  Sharing Memory

Because Unix runs on page architectures, it can use page protections to share sections of memory read-only between processes. For example, the text section for all kshs is shared read-only. Another use of page sharing is for shared libraries. These are subroutines which are common to many programs. The printf() function is used by nearly all C programs, and so it makes sense to load it once into memory, and share its page amongst all C processes.
The ldd command can show you what shared libraries are used by each program:
    $ which ls                          # Where on disk is ls kept?
      /bin/ls
    $ ldd /bin/ls                       # Show the shared libraries used
        librt.so.1 => /lib/librt.so.1 (0x40023000)
        libacl.so.1 => /lib/libacl.so.1 (0x40036000) 
        libc.so.6 => /lib/libc.so.6 (0x4003d000) 
        libpthread.so.0 => /lib/libpthread.so.0 (0x40171000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
        libattr.so.1 => /lib/libattr.so.1 (0x401c2000)
       
    $ size /lib/libc.so.6
      text    data     bss     dec     hex filename
    1228251   11300   10820 1250371  131443 /lib/libc.so.6

Unfortunately, I can't find a tool which shows where and how each shared library is loaded into Linux's memory. As with processes, unused pages in shared libraries are paged out to disk.
Discussion: What disadvantages does a system suffer from if it doesn't provide some form of shared libraries? What disadvantages does a system suffer from if it does provide some form of shared libraries?

7  Memory-related System Calls

7.1  Classic Unix Memory System Calls

Until recently, Unix has provided a flat logical address space to each processes. Available memory locations start at zero and go up to some address N. The text area (containing machine code) was fixed in size, and the stack area grew automagically as a process grew its stack.
The only memory-related system call was to grow or shrink the data area, also known as the heap, which is used to store global variables. This system call was sbrk().
     #include <unistd.h>

     char *sbrk(int incr)

Sbrk() takes a number which indicates by how many bytes to grow the data area. Negative values allow a process to shrink the data area. The system call returns the current top address of the data area; a process can get this information by doing sbrk(0).
On a paged architecture, Unix allocates memory in page units, and so sbrk() will often allocate more new memory than was requested by the process.
The sbrk() call is rarely used directly. Instead, most processes use library routines to create or release new global variables on the heap. Examples are the C routines malloc(), calloc() and free().
Here is an example C program which uses malloc() and free(). Compile and run it using the commands you learned in the last lab.

7.2  Recent Unix Memory System Calls

Unix still only provides a flat address space to processes. We now have system calls to create memory regions between the heap and stack, and to map file contents to these regions. Currently there are two different groups of memory syscalls: the SHM group from System V Unix, and the MMAP group from Berkeley Unix.

7.3  SHM System Calls

     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/shm.h>

     int shmget(key_t key, int size, int flag)

Shmget() allows a process to create a new shared memory object, or to get access to a shared memory object created by another process. The key and flags determine which of the two operations occur. The size field is used to determine the size of a new object. The call returns an integer which identifies the object.
Once a shared memory object has been created or accessed, the process must decide where in its available address space to position the object.
     #include <sys/types.h>
     #include <sys/ipc.h>
     #include <sys/shm.h>

     void *shmat(int shmid, void *addr, int flag)

Shmat() takes an object identifier, and places the memory region in the process' address space starting at location addr. The flag specifies if the object is read-only or read-write.
Another system call, shmdt(), detaches a memory object from a process' address space. A further system call, shmctl(), does other operations like lock the object into main memory, i.e prevent it from ever being paged out out to disk.

8  MMAP System Calls

Berkeley Unix provides another group of memory system calls with similar functionality to SHM. Most current Unixes provide one set as system calls, and have library routines for the other set, which are then translated.
     #include <sys/types.h>
     #include <sys/mman.h>

     void *mmap(void * addr, size_t len, int prot, int flags,
                int fd, off_t offset)

The mmap() system call does a lot in one call! It creates a memory region starting at address addr with length len. Prot specifies if the region is executable, readable and/or writable. Depending on the flags, the region is private, shareable with other processes, and can be mapped to all or a portion of a file specified by fd.
Figs/mmap.gif
When a process is finished with the memory region, it can unmap the region with munmap(). Other system calls like madvise() tell the system how the process will access the region (sequential, random), and if the pages should be locked into main memory.
These system calls also allow shared libraries to exist: if a process requires a shared library, then this is mapped into its address space as a read-only region at run-time.
Here is an example C program which uses mmap() to map a file into memory, read some of its contents and then make changes to the file. Compile and run it using the commands you learned in the last lab.

9  Outlook for the Next Lab

In the next lab, we will look at virtual memory management.


File translated from TEX by TTH, version 3.85.
On 13 Jan 2012, 11:50.