Memory Management in Operating Systems
Memory Management in Operating Systems
UNIT – V
MEMORY MANAGEMENT
Memory management: Contiguous and non-contiguous, Swapping, Paging, Segmentation,
Segmentation with Paging. Virtual Memory: Background, Demand paging, Page replacement
scheme- FIFO, LRU, Optimal, Thrashing.
.
INTRODUCTION :
Memory management is the functionality of an operating system which handles or manages
primary memory and moves processes back and forth between main memory and disk during
execution. Memory management keeps track of each and every memory location, regardless of
either it is allocated to some process or it is free. It checks how much memory is to be allocated
to processes. It decides which process will get memory at what time. It tracks whenever some
memory gets freed or unallocated and correspondingly it updates the status.
80386 Register
The 80386 contains a total of sixteen registers that are of interest to the applications programmer.
As Figure 2-5 shows, these registers may be grouped into these basic categories:
1. General registers. These eight 32-bit general-purpose registers are used primarily to
contain operands for arithmetic and logical operations.
2. Segment registers. These special-purpose registers permit systems software designers to
choose either a flat or segmented model of memory organization. These six registers
determine, at any given time, which segments of memory are currently addressable.
3. Status and instruction registers. These special-purpose registers are used to record and
alter certain aspects of the 80386 processor state.
The general registers of the 80386 are the 32-bit registers EAX, EBX, ECX, EDX, EBP, ESP,
ESI, and EDI. These registers are used interchangeably to contain the operands of logical and
arithmetic operations. They may also be used interchangeably for operands of address
computations (except that ESP cannot be used as an index operand).
As Figure 2-5 shows, the low-order word of each of these eight registers has a separate name and
can be treated as a unit. This feature is useful for handling 16-bit data items and for compatibility
with the 8086 and 80286 processors. The word registers are named AX, BX, CX, DX, BP, SP,
SI, and DI.
Figure 2-5 also illustrates that each byte of the 16-bit registers AX, BX, CX, and DX has a
separate name and can be treated as a unit. This feature is useful for handling characters and
other 8-bit data items. The byte registers are named AH, BH, CH, and DH (high bytes); and AL,
BL, CL, and DL (low bytes).
All of the general-purpose registers are available for addressing calculations and for the results of
most arithmetic and logical calculations; however, a few functions are dedicated to certain
registers. By implicitly choosing registers for these functions, the 80386 architecture can encode
instructions more compactly. The instructions that use specific registers include: double-
precision multiply and divide, I/O, string instructions, translate, loop, variable shift and rotate,
and stack operations.
The segment registers of the 80386 give systems software designers the flexibility to choose
among various models of memory organization. Implementation of memory models is the
subject of Part II -- Systems Programming. Designers may choose a model in which applications
programs do not need to modify segment registers, in which case applications programmers may
skip this section.
Complete programs generally consist of many different modules, each consisting of instructions
and data. However, at any given time during program execution, only a small subset of a
program's modules are actually in use. The 80386 architecture takes advantage of this by
providing mechanisms to support direct access to the instructions and data of the current
module's environment, with access to additional segments on demand.
At any given instant, six segments of memory may be immediately accessible to an executing
80386 program. The segment registers CS, DS, SS, ES, FS, and GS are used to identify these six
current segments. Each of these registers specifies a particular kind of segment, as characterized
by the associated mnemonics ("code," "data," or "stack") shown in Figure 2-6 . Each register
uniquely determines one particular segment, from among the segments that make up the
program, that is to be immediately accessible at highest speed.
The segment containing the currently executing sequence of instructions is known as the current
code segment; it is specified by means of the CS register. The 80386 fetches all instructions from
this code segment, using as an offset the contents of the instruction pointer. CS is changed
implicitly as the result of intersegment control-transfer instructions (for
example, CALL and JMP), interrupts, and exceptions.
Subroutine calls, parameters, and procedure activation records usually require that a region of
memory be allocated for a stack. All stack operations use the SS register to locate the stack.
Unlike CS, the SS register can be loaded explicitly, thereby permitting programmers to define
stacks dynamically.
The DS, ES, FS, and GS registers allow the specification of four data segments, each addressable
by the currently executing program. Accessibility to four separate data areas helps programs
efficiently access different types of data structures; for example, one data segment register can
point to the data structures of the current module, another to the exported data of a higher-level
module, another to a dynamically created data structure, and another to data shared with another
task. An operand within a data segment is addressed by specifying its offset either directly in an
instruction or indirectly via general registers.
Depending on the structure of data (e.g., the way data is parceled into one or more segments), a
program may require access to more than four data segments. To access additional segments, the
DS, ES, FS, and GS registers can be changed under program control during the course of a
program's execution. This simply requires that the program execute an instruction to load the
appropriate segment register prior to executing instructions that access the data.
The processor associates a base address with each segment selected by a segment register. To
address an element within a segment, a 32-bit offset is added to the segment's base address. Once
a segment is selected (by loading the segment selector into a segment register), a data
manipulation instruction only needs to specify the offset. Simple rules define which segment
register is used to form an address when only an offset is specified.
1. The stack segment (SS) register. Stacks are implemented in memory. A system may have
a number of stacks that is limited only by the maximum number of segments. A stack
may be up to 4 gigabytes long, the maximum length of a segment. One stack is directly
addressable at a -- one located by SS. This is the current stack, often referred to simply as
"the" stack. SS is used automatically by the processor for all stack operations.
2. The stack pointer (ESP) register. ESP points to the top of the push-down stack (TOS). It
is referenced implicitly by PUSH and POP operations, subroutine calls and returns, and
interrupt operations. When an item is pushed onto the stack (see Figure 2-7 ), the
processor decrements ESP, then writes the item at the new TOS. When an item is popped
off the stack, the processor copies it from TOS, then increments ESP. In other words, the
stack grows down in memory toward lesser addresses.
3. The stack-frame base pointer (EBP) register. The EBP is the best choice of register for
accessing data structures, variables and dynamically allocated work space within the
stack. EBP is often used to access elements on the stack relative to a fixed point on the
stack rather than relative to the current TOS. It typically identifies the base address of the
current stack frame established for the current procedure. When EBP is used as the base
register in an offset calculation, the offset is calculated automatically in the current stack
segment (i.e., the segment currently selected by SS). Because SS does not have to be
explicitly specified, instruction encoding in such cases is more efficient. EBP can also be
used to index into segments addressable via other segment registers.
The flags register is a 32-bit register named EFLAGS. Figure 2-8 defines the bits within this
register. The flags control certain operations and indicate the status of the 80386.
The low-order 16 bits of EFLAGS is named FLAGS and can be treated as a unit. This feature is
useful when executing 8086 and 80286 code, because this part of EFLAGS is identical to the
FLAGS register of the 8086 and the 80286.
The flags may be considered in three groups: the status flags, the control flags, and the systems
flags. Discussion of the systems flags is delayed until Part II.
As Figure 2-9 shows, the low-order 16 bits of EIP is named IP and can be used by the processor
as a unit. This feature is useful when executing instructions designed for the 8086 and 80286
processors.
Garbage collection: Some programs use dynamic data structures. These programs
dynamically use and discard memory space. Technically, the deleted data items (from a
dynamic data structure) release memory locations. However, in practice the OS does not
collect such free space immediately for allocation. as specialized files. Their buffers need
to be managed within main memory alongside the other processes. The considerations
stated above motivate the study of main memory managementSuch areas, therefore, are
called garbage. When such garbage exceeds a certain threshold, the OS would not have
enough memory available for any further allocation. This entails compaction (or garbage
collection), without severely affecting performance.
Protection: With many programs residing in main memory it can happen that due to a
programming error (or with malice) some process writes into data or instruction area of
some other process. The OS ensures that each process accesses only to its own allocated
area, i.e. each process is protected from other processes.
Virtual memory: Often a processor sees a large logical storage space (a virtual storage
space) though the actual main memory may not be that large. So some facility needs to be
provided to translate a logical address available to a processor into a physical address to
access the desired data or instruction.
IO support: Most of the block-oriented devices are recognized as specialized files. Their
buffers need to be managed within main memory alongside the other processes. The
considerations stated above motivate the study of main memory management.
5. Worst fit: The memory manager places a process in the largest block of unallocated
memory available. The idea is that this placement will create the largest hold after the
allocations, thus increasing the possibility that, compared to best fit, another process can
use the remaining space. Using the same example as above, worst fit will allocate 12KB
of the 19KB block to the process, leaving a 7KB block for future use.
6. First fit: There may be many holes in the memory, so the operating system, to reduce the
amount of time it spends analyzing the available spaces, begins at the start of primary
memory and allocates memory from the first hole it encounters large enough to satisfy
the request. Using the same example as above, first fit will allocate 12KB of the 14KB
block to the process.
Primary
Best fit Worst fit First fit
Memory
Notice in the diagram above that the Best fit and First fit strategies both leave a tiny segment of
memory unallocated just beyond the new process. Since the amount of memory is small, it is not
likely that any new processes can be loaded here. This condition of splitting primary memory
into segments as the memory is allocated and deallocated is known as fragmentation. The Worst
fit strategy attempts to reduce the problem of fragmentation by allocating the largest fragments to
new processes. Thus, a larger amount of space will be left as seen in the diagram above.
Figure 8.1 - A base and a limit register define a logical addresss space
Figure 8.2 - Hardware address protection with base and limit registers
User programs typically refer to memory addresses with symbolic names such as "i",
"count", and "averageTemperature". These symbolic names must be mapped or bound to
physical memory addresses, which typically occurs in several stages:
o Compile Time - If it is known at compile time where a program will reside in
physical memory, then absolute code can be generated by the compiler,
containing actual physical addresses. However if the load address changes at
some later time, then the program will have to be recompiled. DOS .COM
programs use compile time binding.
o Load Time - If the location at which a program will be loaded is not known at
compile time, then the compiler must generate relocatable code, which references
addresses relative to the start of the program. If that starting address changes, then
the program must be reloaded but not recompiled.
o Execution Time - If a program can be moved around in memory during the
course of its execution, then binding must be delayed until execution time. This
requires special hardware, and is the method implemented by most modern OSes.
Figure 8.3 shows the various stages of the binding processes and the units involved in
each stage:
The address generated by the CPU is a logical address, whereas the address actually seen
by the memory hardware is a physical address.
Addresses bound at compile time or load time have identical logical and physical
addresses.
Addresses created at execution time, however, have different logical and physical
addresses.
o In this case the logical address is also known as a virtual address, and the two
terms are used interchangeably by our text.
o The set of all logical addresses used by a program composes the logical address
space, and the set of all corresponding physical addresses composes the physical
address space.
The run time mapping of logical to physical addresses is handled by the memory-
management unit, MMU.
o The MMU can take on many forms. One of the simplest is a modification of the
base-register scheme described earlier.
o The base register is now termed a relocation register, whose value is added to
every memory request at the hardware level.
Note that user programs never see physical addresses. User programs work entirely in
logical address space, and any memory references or manipulations are done using purely
logical addresses. Only when the address gets sent to the physical memory chips is the
physical memory address generated.
Rather than loading an entire program into memory at once, dynamic loading loads up
each routine as it is called. The advantage is that unused routines need never be loaded,
reducing total memory usage and generating faster program startup times. The downside
is the added complexity and overhead of checking to see if a routine is loaded every time
it is called and then then loading it up if it is not already loaded.
With static linking library modules get fully included in executable modules, wasting
both disk space and main memory usage, because every program that included a certain
routine from the library would have to have their own copy of that routine linked into
their executable code.
With dynamic linking, however, only a stub is linked into the executable module,
containing references to the actual library module linked in at run time.
o This method saves disk space, because the library routines do not need to be fully
included in the executable modules, only the stubs.
o We will also learn that if the code section of the library routines is reentrant,
( meaning it does not modify the code while it runs, making it safe to re-enter it ),
then main memory can be saved by loading only one copy of dynamically linked
routines into memory and sharing the code amongst all processes that are
concurrently using it. ( Each process would have their own copy of
the data section of the routines, but that may be small relative to the code
segments. ) Obviously the OS must manage shared routines in memory.
o An added benefit of dynamically linked libraries ( DLLs, also known as shared
libraries or shared objects on UNIX systems ) involves easy upgrades and
updates. When a program uses a routine from a standard library and the routine
changes, then the program must be re-built ( re-linked ) in order to incorporate the
changes. However if DLLs are used, then as long as the stub doesn't change, the
program can be updated merely by loading new versions of the DLLs onto the
system. Version information is maintained in both the program and the DLLs, so
that a program can specify a particular version of the DLL if necessary.
o In practice, the first time a program calls a DLL routine, the stub will recognize
the fact and will replace itself with the actual routine from the DLL library.
Further calls to the same routine will access the routine directly and not incur the
overhead of the stub access. ( Following the UML Proxy Pattern. )
o ( Additional information regarding dynamic linking is available
at [Link] )
Swapping
Swapping is a mechanism in which a process can be swapped temporarily out of main memory
(or move) to secondary storage (disk) and make that memory available to other processes. At
some later time, the system swaps back the process from the secondary storage to main
memory.
Though performance is usually affected by swapping process but it helps in running multiple
and big processes in parallel and that's the reason Swapping is also known as a technique for
memory compaction.
The total time taken by swapping process includes the time it takes to move the entire process to
a secondary disk and then to copy the process back to memory, as well as the time the process
takes to regain main memory.
Let us assume that the user process is of size 2048KB and on a standard hard disk where
swapping will take place has a data transfer rate around 1 MB per second. The actual transfer of
the 1000K process to or from memory will take
1 Single-partition allocation
In this type of allocation, relocation-register scheme is used to protect user
processes from each other, and from changing operating-system code and data.
Relocation register contains value of smallest physical address whereas limit
register contains range of logical addresses. Each logical address must be less than
the limit register.
2 Multiple-partition allocation
In this type of allocation, main memory is divided into a number of fixed-sized
partitions where each partition should contain only one process. When a partition is
free, a process is selected from the input queue and is loaded into the free partition.
When the process terminates, the partition becomes available for another process.
Fragmentation
As processes are loaded and removed from memory, the free memory space is broken into little
pieces. It happens after sometimes that processes cannot be allocated to memory blocks
considering their small size and memory blocks remains unused. This problem is known as
Fragmentation.
Fragmentation is of two types −
1 External fragmentation
Total memory space is enough to satisfy a request or to reside a process in it, but it
is not contiguous, so it cannot be used.
2 Internal fragmentation
Memory block assigned to process is bigger. Some portion of memory is left
unused, as it cannot be used by another process.
The following diagram shows how fragmentation can cause waste of memory and a compaction
technique can be used to create more free memory out of fragmented memory −
External fragmentation can be reduced by compaction or shuffle memory contents to place all
free memory together in one large block. To make compaction feasible, relocation should be
dynamic.
The internal fragmentation can be reduced by effectively assigning the smallest partition but
large enough for the process.
Paging
A computer can address more memory than the amount physically installed on the system. This
extra memory is actually called virtual memory and it is a section of a hard that's set up to
emulate the computer's RAM. Paging technique plays an important role in implementing virtual
memory.
Paging is a memory management technique in which process address space is broken into
blocks of the same size called pages (size is power of 2, between 512 bytes and 8192 bytes).
The size of the process is measured in the number of pages.
Similarly, main memory is divided into small fixed-sized blocks of (physical) memory
called frames and the size of a frame is kept the same as that of a page to have optimum
utilization of the main memory and to avoid external fragmentation.
Address Translation
Page address is called logical address and represented by page numberand the offset.
When the system allocates a frame to any page, it translates this logical address into a physical
address and create entry into the page table to be used throughout execution of the program.
When a process is to be executed, its corresponding pages are loaded into any available memory
frames. Suppose you have a program of 8Kb but your memory can accommodate only 5Kb at a
given point in time, then the paging concept will come into picture. When a computer runs out
of RAM, the operating system (OS) will move idle or unwanted pages of memory to secondary
memory to free up RAM for other processes and brings them back when needed by the
program.
This process continues during the whole execution of the program where the OS keeps
removing idle pages from the main memory and write them onto the secondary memory and
bring them back when required by the program.
Advantages and Disadvantages of Paging
Here is a list of advantages and disadvantages of paging −
Paging reduces external fragmentation, but still suffer from internal fragmentation.
Paging is simple to implement and assumed as an efficient memory management
technique.
Due to equal size of the pages and frames, swapping becomes very easy.
Page table requires extra memory space, so may not be good for a system having small
RAM.
Segmentation
Segmentation is a memory management technique in which each job is divided into several
segments of different sizes, one for each module that contains pieces that perform related
functions. Each segment is actually a different logical address space of the program.
When a process is to be executed, its corresponding segmentation are loaded into non-
contiguous memory though every segment is loaded into a contiguous block of available
memory.
Segmentation memory management works very similar to paging but here segments are of
variable-length where as in paging pages are of fixed size.
A program segment contains the program's main function, utility functions, data structures, and
so on. The operating system maintains a segment map table for every process and a list of free
memory blocks along with segment numbers, their size and corresponding memory locations in
main memory. For each segment, the table stores the starting address of the segment and the
length of the segment. A reference to a memory location includes a value that identifies a
segment and an offset.
Virtual memory :
computer can address more memory than the amount physically installed on the system. This
extra memory is actually called virtual memory and it is a section of a hard disk that's set up to
emulate the computer's RAM.
The main visible advantage of this scheme is that programs can be larger than physical memory.
Virtual memory serves two purposes. First, it allows us to extend the use of physical memory
by using disk. Second, it allows us to have memory protection, because each virtual address is
translated to a physical address.
Following are the situations, when entire program is not required to be loaded fully in main
memory.
User written error handling routines are used only when an error occurred in the data or
computation.
Certain options and features of a program may be used rarely.
Many tables are assigned a fixed amount of address space even though only a small
amount of the table is actually used.
The ability to execute a program that is only partially in memory would counter many
benefits.
Less number of I/O would be needed to load or swap each user program into memory.
A program would no longer be constrained by the amount of physical memory that is
available.
Each user program could take less physical memory, more programs could be run the
same time, with a corresponding increase in CPU utilization and throughput.
Modern microprocessors intended for general-purpose use, a memory management unit, or
MMU, is built into the hardware. The MMU's job is to translate virtual addresses into physical
addresses. A basic example is given below −
Demand Paging
A demand paging system is quite similar to a paging system with swapping where processes
reside in secondary memory and pages are loaded only on demand, not in advance. When a
context switch occurs, the operating system does not copy any of the old program’s pages out to
the disk or any of the new program’s pages into the main memory Instead, it just begins
executing the new program after loading the first page and fetches that program’s pages as they
are referenced.
While executing a program, if the program references a page which is not available in the main
memory because it was swapped out a little ago, the processor treats this invalid memory
reference as a page fault and transfers control from the program to the operating system to
demand the page back into the memory.
Advantages
Following are the advantages of Demand Paging −
Easy to implement, keep a list, replace pages from the tail and add new pages at the
head.
FIFO is not a stack algorithm. In certain cases, the number of page faults can actually increase
when more frames are allocated to the process. In the example below, there are 9 page faults for
3 frames and 10 page faults for 4 frames.
Optimal Replacement
The Belady’s optimal algorithm cheats. It looks forward in time to see which frame to replace on
a page fault. Thus it is not a real replacement algorithm. It gives us a frame of reference for a
given static frame access sequence.
While using memory mapped IO, OS allocates buffer in memory and informs I/O device to use
that buffer to send data to the CPU. I/O device operates asynchronously with CPU, interrupts
CPU when finished.
The advantage to this method is that every instruction which can access memory can be used to
manipulate an I/O device. Memory mapped IO is used for most high-speed I/O devices like
disks, communication interfaces.
Direct Memory Access (DMA)
Slow devices like keyboards will generate an interrupt to the main CPU after each byte is
transferred. If a fast device such as a disk generated an interrupt for each byte, the operating
system would spend most of its time handling these interrupts. So a typical computer uses direct
memory access (DMA) hardware to reduce this overhead.
Direct Memory Access (DMA) means CPU grants I/O module authority to read from or write to
memory without involvement. DMA module itself controls exchange of data between main
memory and the I/O device. CPU is only involved at the beginning and end of the transfer and
interrupted only after entire block has been transferred.
Direct Memory Access needs a special hardware called DMA controller (DMAC) that manages
the data transfers and arbitrates access to the system bus. The controllers are programmed with
source and destination pointers (where to read/write the data), counters to track the number of
transferred bytes, and settings, which includes I/O and memory types, interrupts and states for
the CPU cycles.
Step Description
5 DMA controller transfers bytes to buffer, increases the memory address, decreases
the counter C until C becomes zero.
Device Drivers
Device drivers are software modules that can be plugged into an OS to handle a particular
device. Operating System takes help from device drivers to handle all I/O devices. Device
drivers encapsulate device-dependent code and implement a standard interface in such a way
that code contains device-specific register reads/writes. Device driver, is generally written by
the device's manufacturer and delivered along with the device on a CD-ROM.
A device driver performs the following jobs −
When the interrupt happens, the interrupt procedure does whatever it has to in order to handle
the interrupt, updates data structures and wakes up process that was waiting for an interrupt to
happen.
The interrupt mechanism accepts an address ─ a number that selects a specific interrupt
handling routine/function from a small set. In most architectures, this address is an offset stored
in a table called the interrupt vector table. This vector contains the memory addresses of
specialized interrupt handlers.
Device-Independent I/O Software
The basic function of the device-independent software is to perform the I/O functions that are
common to all devices and to provide a uniform interface to the user-level software. Though it
is difficult to write completely device independent software but we can write some modules
which are common among all the devices. Following is a list of functions of device-independent
I/O Software −
application operation. Buffering is done to cope with a speed mismatch between the
producer and consumer of a data stream or to adapt between devices that have different
data transfer sizes.
Caching − Kernel maintains cache memory which is region of fast memory that holds
copies of data. Access to the cached copy is more efficient than access to the original.
Spooling and Device Reservation − A spool is a buffer that holds output for a device,
such as a printer, that cannot accept interleaved data streams. The spooling system
copies the queued spool files to the printer one at a time. In some operating systems,
spooling is managed by a system daemon process. In other operating systems, it is
handled by an in kernel thread.
Error Handling − An operating system that uses protected memory can guard against
many kinds of hardware and application errors.
Segmentation
In Operating Systems, Segmentation is a memory management technique in which, the memory
is divided into the variable size parts. Each part is known as segment which can be allocated to a
process.
The details about each segment are stored in a table called as segment table. Segment table is
stored in one (or many) of the segments.
Till now, we were using Paging as our main memory management technique. Paging is more
close to Operating system rather than the User. It divides all the process into the form of pages
regardless of the fact that a process can have some relative parts of functions which needs to be
loaded in the same page.
Operating system doesn't care about the User's view of the process. It may divide the same
function into different pages and those pages may or may not be loaded at the same time into the
memory. It decreases the efficiency of the system.
It is better to have segmentation which divides the process into the segments. Each segment
contain same type of functions such as main function can be included in one segment and the
library functions can be included in the other segment,
1. Segment Number
2. Offset
The Segment number is mapped to the segment table. The limit of the respective segment is
compared with the offset. If the offset is less than the limit then the address is valid otherwise it
throws an error as the address is invalid.
In the case of valid address, the base address of the segment is added to the offset to get the
physical address of actual word in the main memory.
Advantages of Segmentation
1. No internal fragmentation
2. Average Segment Size is larger than the actual page size.
3. Less overhead
4. It is easier to relocate segments than entire address space.
5. The segment table is of lesser size as compare to the page table in paging.
Disadvantages
1. It can have external fragmentation.
2. it is difficult to allocate contiguous memory to variable sized partition.
3. Costly memory management algorithms.
Paging VS Segmentation
Sr Paging Segmentation
No.
2 Paging divides program into fixed size Segmentation divides program into
pages. variable size segments.
8 Logical address is divided into page Logical address is divided into segment
number and page offset number and segment offset
9 Page table is used to maintain the Segment Table maintains the segment
page information. information
10 Page table entry has the frame Segment table entry has the base
number and some flag bits to address of the segment and some
represent details about pages. protection bits for the segments.
Thrashing :
Thrashing is computer activity that makes little or no progress, usually because memory or other
resources have become exhausted or too limited to perform needed operations. When this
happens, a pattern typically develops in which a request is made of the operating system by a
process or program, the operating system tries to find resources by taking them from some other
process, which in turn makes new requests that can't be satisfied. In a virtual storage system (an
operating system that manages its logical storage or memory in units called pages), thrashing is a
condition in which excessive paging operations are taking place.
A system that is thrashing can be perceived as either a very slow system or one that has come to
a halt.