Operating Systems - Storage Management (Night Class)
Compiled
By Aurelie A. Peralta
The main
purpose of a computer system is to execute programs. These programs, together with
the data they access, must be in main memory (at least partially) during execution.
To improve
both the utilization of the CPU and the speed of its response to users, the computer
must keep several processes in memory. Many memory-management schemes exist, reflecting
various approaches, and the effectiveness of each algorithm depends on the situation.
Selection of a memory-management scheme for a system depends on many factors, especially on the hardware design of the system. Each algorithm requires its own hardware support.
Since main
memory is usually too small to accommodate all the data and programs permanently,
the computer system must provide secondary storage to back-up main memory. Modern
computer systems use disks as the primary on-line storage medium for information
(both programs and data). The file system provides the mechanism for on-line storage
of and access to both data and programs residing on the disks. A file is a collection
of related information defined by its creator. The files are mapped by the operating
system onto physical devices. Files are normally organized into directories to ease
their use.
Memory Management
The CPU
can be shared by a set of processes. As a result of CPU scheduling, we can improve
both the utilization of the CPU and the speed of the computer’s response to its
users. To realize this increase in performance, however, we must keep several
processes in memory; that is, we must share memory.
Memory
is central to the operation of a modern computer system. Memory consists of a large
array of words or bytes, each with its own address. The CPU fetches instructions
from the memory
according to the
value of the program counter. These instructions
may cause additional loading from and storing to specific memory addresses.
Address Binding
Usually,
a program resides on disk as a binary executable file. The program must be brought
into memory and placed within a process for it to be executed. Depending on the memory management in use, the process may be moved between disk and memory during
execution. The collection of processes on the disk that is waiting to be brought
into memory for execution forms the input queue.
The normal procedure is to select one of the processes in the input queue and to load that
process into memory. As the process is executed, it accesses instructions and data
from memory. Eventually, the process terminates, and its memory space is declared
available.
Classically,
the binding of instructions and data to memory addresses can be done at any step
along the way:
1. Compile
time: If you know at compile time where the process will reside in memory, then
absolute code can be generated.
2. Load
time: If it is not known at compile time where the process will reside in memory,
then the computer must generate relocatable code.
3. Execution
time: If the process can be moved during execution from one memory segment to another,
then binding must be delayed until run time.
Logical- Versus Physical-Address Space
An address
generated by the CPU is commonly referred to as a logical address, whereas an address
seen by the memory unit - that is, the one loaded into the memory-address register
of the memory - is commonly called to as a physical address.
The compile-time
and load-time address-binding methods generate identical logical and physical addresses.
However, the execution-time address-binding scheme results in differing logical
and physical addresses. In this case, we usually refer to the logical address as
a virtual address. We use logical address and virtual address interchangeably. The
set of all logical addresses generated by a program is a logical-address space;
the set of all physical addresses corresponding to these logical addresses is a
physical-address space. Thus, in the execution-time address-binding scheme, the
logical- and physical-address spaces differ.
Dynamic Loading
To obtain
better memory-space utilization, we can use dynamic loading. With dynamic loading,
a routine is not loaded until it is called. The advantage of dynamic loading is
that an unused routine is never loaded. This method is particularly useful when
large amounts of code are needed to handle infrequently occurring cases, such as
error routines.
Dynamic Linking and Shared Libraries
The concept
of dynamic linking is similar to that of dynamic loading. Rather than loading being
postponed until execution time, linking is postponed. This feature is usually used
with system libraries, such as language subroutine libraries.
More than
one version of a library may be loaded into memory, and each program uses its version
information to decide which copy of the library to use. Minor changes retain the
same version number, whereas major changes increment the version number. Thus, only
programs that are compiled with the new library version are affected by the incompatible
changes incorporated in it. Other programs linked before the new library was installed
will continue using the older library. This system is also known as shared libraries.
Unlike
dynamic loading, dynamic linking generally requires help from the operating system.
Overlays
To enable
a process to be larger than the amount of memory allocated to it, we can use overlays.
The idea of overlays is to keep in memory only those instructions and data that
are needed at any given time. When other instructions are needed, they are loaded
into space occupied previously by instructions that are no longer needed.
As in dynamic
loading, overlays do not require any special support from the operating system.
They can be implemented completely by the user with simple file structures, reading
from the files into memory and then jumping to that memory and executing the newly
read instructions. The operating system notices only that there is more I/O than
usual.
The programmer
on the other hand, must design and program the overlay structure properly.
Swapping
A process
needs to be in memory to be executed. A process, however, can be swapped temporarily
out of memory to a backing store, and then brought back into memory for continued
execution.
A variant
of this swapping policy is used for priority-based scheduling algorithms. If a higher-priority
process arrives and wants service, the memory manager can swap out the lower-priority
process so that it can load and execute the higher-priority process. When the higher-priority
process finishes, the lower-priority process can be swapped back in and continued.
This variant of swapping is sometimes called roll out, roll in.
Swapping
requires a backing store. The backing store is commonly a fast disk. It must be
large enough to accommodate copies of all memory images for all users, and it must
provide direct access to these memory images. The system maintains a ready queue
consisting of all processes whose memory images are on the backing store or in memory
and are ready to run.
Contiguous Memory Allocation
The main
memory must accommodate both the operating system and the various user processes.
We therefore need to allocate different parts of the main memory in the most efficient
way possible. One method to accomplish this is by using a contiguous memory allocation
method.
The memory
is usually divided into two partitions: one for the resident operating system, and
one for the user processes. We may place the operating system in either low memory
or high memory. The major factor affecting this decision is the location of the
interrupt vector. Since the interrupt vector is often in low memory, programmers
usually place the operating system in low memory as well.
We usually
want several user processes to reside in memory at the same time. We therefore need
to consider how to allocate available memory to the processes that are in the input
queue waiting to be brought into memory. In this contiguous memory allocation, each
process is contained in a single contiguous section of memory.
Memory Protection
Memory
protection is all about protecting the operating system from user processes, and
protecting user processes from one another.
The relocation-register
scheme provides an effective way to allow the operating-system size to change dynamically.
This flexibility is desirable in many situations. A code that comes and goes as
needed is called transient operating-system code.
Memory Allocation
One of
the simplest methods for memory allocation is to divide memory into several fixed-sized
partitions. Each partition may contain exactly one process. Thus, the degree of
multi-programming is bound by the number of partitions.
The operating
system keeps a table indicating which parts of memory are available and which are
occupied. Initially, all memory is available for user processes, and is considered
as one large
block of available memory, a hole. When a process arrives and needs
memory, we search for a hole large enough for this process. If we find one, we allocate
only as much memory as is needed, keeping the rest available to satisfy future requests.
The first-fit,
best-fit, and worst-fit strategies are the most common ones used to select a free
hole from the set of available holes.
1. First-fit
- allocate the first hole that is big enough.
2. Best-fit
- allocate te smallest hole that is big enough.
3. Worst-fit
- allocate the largest hole.
These algorithms,
however, suffer from external fragmentation. As processes are loaded and removed
from memory, the free memory space is broken into little pieces.
Fragmentation
Memory
fragmentation can be internal as well as external. Internal fragmentation is the
memory that is internal to a partition but is not being used. One solution to the
problem of external fragmentation is compaction. The goal is to shuffle the memory
contents to place all free memory together in one large block. Compaction is not
always possible.
Paging
Paging
is a memory-management scheme that permits the physical-address space of a process
to be noncontiguous. Paging avoids the considerable problem of fitting the varying-sized
memory chunks onto the backing store, from which most of the previous memory-management
schemes suffered.
Segmentation
Users prefer
to view memory as a collection of variable-sized segments, with no necessary ordering
among segments.
Segmentation
is a memory-management scheme that supports this user view of memory. A logical-address
space is a collection of segments. Each segment has a name and a length.
Summary
Memory-management
algorithms for multiprogrammed operating systems rage from the simple single-user
system approach to paged segmentation. The greatest determinant of the method used
in particular system is the hardware provided. Every memory address generated by
the CPU must be checked for legality and possibly mapped to a physical address.
the checking cannot be implemented efficiently in
software. Hence, we are constrained
by the hardware available.
The memory-management
algorithms discussed differ in many aspects. In comparing different memory-management
strategies, you should use the following considerations:
1. Hardware
support
2. Performance
3. Fragmentation
- memory waste
4. Relocation
- compaction
5. Swapping
6. Sharing
7. Protection
Reference: Operating System Concepts by Silberschatz, Galvin, and Gagne, 2003