Os - Unit 4
Os - Unit 4
C
Swapping processes in and out of main memory.
4.1.2 Address Binding
Usually, a program resides on a 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 its execution. The collection of processes on
the disk that is waiting to be brought into memory for execution forms the input queue.
EM
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. Most systems allow a user process to
reside in any part of the physical memory. Thus, although the address space of the computer starts at
00000, the first address of the user process does not need to be 00000. This arrangement affects the
addresses that the user program can use. In most cases, a user program will go through several steps-some
of which may be optional-before being executed (Figure 4.1). Addresses may be represented in different
ways during these steps. Addresses in the source program are generally symbolic (such as count). A
compiler will typically bind these symbolic addresses to relocatable addresses (such as "14 bytes from the
beginning of this module").The linkage editor or loader will in turn bind these relocatable addresses to
absolute addresses (such as 74014). Each binding is a mapping from one address space to another.
The address binding is binding instructions and data to memory address. This binding can be done at
C
either
Compile time
Load time
EM
Execution time
Compile Time Binding: if u knows at the compile time where the process resides in memory, then the
absolute code can be generated. The Process must reside in same memory region for it to execute
correctly.
Example: if it knows priori that a user process will start at location R, then the generated compiler code
will start at that location and extend up from there.
Load time Binding: If it is not known at compile time where the process will reside in memory, then the
compiler must generate relocatable code. In this case, final binding is delayed until load time. If the
starting address changes, we need only to reload the user code to incorporate this changed value. The
Process can be loaded in different memory regions in the case of load time binding since the address is
binded only at load time.
Execution time: If the process can be moved during its execution from one memory segment to another,
then binding must be delayed until runtime. Most general-purpose operating systems use this method.
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
referred to as a physical address. 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
C
physical-address space. The run-time mapping from virtual to physical addresses is done by a hardware
device called the memory-management unit (MMU).The figure is as shown in fig 3.3. The base register is
called the relocation register. The relocation register is a special register in the CPU that helps in
relocation of a program. It contains an integer number. The CPU adds this number to every address
generated during execution of a program. The result is another memory address, which is used to make a
EM
memory reference.
Example
A program is prepared for execution in a memory area starting on the address 50000. We call this the
assumed start address. Let the memory area allocated to the programs execution have the start address of
70000. Then the relocation of the program is achieved simply by loading an appropriate value to the
relocation register. The value loaded in relocation register = start address of the allocated memory –
assumed start address = 70000 – 50000 =20000
Our earlier Concept is that the entire program and data of a process must be in physical memory for the
process to execute. The size of a process is limited to the size of physical memory. To obtain better
memory-space utilization, we can use dynamic loading. With dynamic loading, a routine is not loaded
until it is called. All routines are kept on disk in a relocatable load format. The main program is loaded
into memory and is executed. When a routine needs to call another routine, the calling routine first checks
to see whether the other routine has been loaded. If not, the relocatable linking loader is called to load the
desired routine into memory and to update the program's address tables to reflect this change. Then,
control is passed to the newly loaded routine. 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
C
infrequently occurring cases, such as error routines. In this case, although the total program size may be
large, the portion that is used (and hence loaded) may be much smaller.
Dynamic loading does not require special support from the operating system. It is the
responsibility of the users to design their programs to take advantage of such a method. Operating systems
may help the programmer, however, by providing library routines to implement dynamic loading.
EM
4.1.5 Dynamic Linking and Shared Libraries
Figure 4.1 shows dynamically linked libraries. Some operating systems support only static linking, in
which system language libraries are treated like any other object module and are combined by the loader
into the binary program image. 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.
With dynamic linking, a stub is included in the image for each library-routine reference. This stub is a
small piece of code that indicates how to locate the appropriate memory-resident library routine, or how
to load the library if the routine is not already present. When this stub is executed, it checks to see
whether the needed routine is already in memory. If not, the program loads the routine into memory.
The stub replaces itself with the address of the routine, and executes the routine. Thus, the next time that
that code segment is reached, the library routine is executed directly, incurring no cost for dynamic
linking. Under this scheme, all processes that use a language library execute only one copy of the library
code.
A library may be replaced by a new version, and all programs that reference the library will automatically
use the new version. Without dynamic linking, all such programs would need to be relinked to gain access
to the new library. So that programs will not accidentally execute new, incompatible versions of libraries,
version information is included in both the program and the library. 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.
4.2 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. For example,
assume a multiprogramming environment with a round-robin CPU-scheduling algorithm. When a
quantum expires, the memory manager will start to swap out the process that just finished, and to swap in
another process to the memory space (fig:4.4). In the meantime, the CPU scheduler will allocate a time
slice to some other process in memory. When each process finishes its quantum, it will be swapped with
another process.
C
Normally a process that is swapped out will be swapped back into the same memory space that it
occupied previously. This restriction is dictated by the method of address binding. If binding is done at
assembly or load time, then the process cannot be moved to different locations. If execution-time binding
is being used, then a process can be swapped into a different memory space, because the physical
addresses are computed during execution time.
EM
Figure 4.4:swapping of two processes using a disk as a backing store
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. Whenever the CPU scheduler decides to
execute a process, it calls the dispatcher. The dispatcher checks to see whether the next process in the
queue is in memory. If not, and there is no free memory region, the dispatcher swaps out a process
currently in memory and swaps in the desired process. It then reloads registers as normal and transfers
control to the selected process.
The context-switch time in such a swapping system is fairly high. To get an idea of the context-switch
time, let us assume that the user process is of size 1MB and the backing store is a standard hard disk with
a transfer rate of 5 MB per second. The actual transfer of the 1 MB process to or from memory takes
1000 KB/5000 KB per second = 1 /5 second
= 200 milliseconds.
The major part of the swap time is transfer time. The total transfer time is directly proportional to the
amount of memory swapped. If we are using Round Robin (RR) scheduling then the system should select
an appropriate time Quantum. Otherwise, there will be frequent swapping in certain conditions.
The other issue is regarding the pending I/O. that is if we want to swap a process, we must be sure that it
is completely idle or check whether there is any pending I/O. A process may be waiting for an I/O
operation when we want to swap that process to free up its memory. However, if the I/O is
asynchronously accessing the user memory for I/O buffers, then the process cannot be swapped. Assume
C
that the I/O operation was queued because the device was busy. Then, if we were to swap out process P1
and swap in process P2, the I/O operation might then attempt to use memory that now belongs to process
P2.The two main solutions to this problem are never to swap a process with pending I/O, or to execute I/O
operations only into operating-system buffers. Transfers between operating-system buffers and process
memory then occur only when the process is swapped in.
EM
4.3.Contiguous Memory Allocation
The main memory must accommodate both the operating system and the various user processes. We need
to allocate the parts of the main memory in the most efficient way possible. The memory is usually
divided into two partitions: one for the resident OS and one for the user processes. We can place the
operating system in either low memory or high memory. 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 contiguous memory allocation, each process is
contained in a single section of memory that is contiguous to the section containing the next process.
In a single user system, the system must protect only the OS from the user process. But in a
multiprogramming system, the system must protect the operating system from all user processes and
protect each process from all other process. The system can delimit each partition with two boundary
registers called base and limit registers.
Here the base register contains the starting address of a partition and the limit contains the ending address
of a partition. When a process issues a memory request, the system checks whether the requested address
is greater than or equal to the process base register value and less than the process limit register value. If
so, the system allows the request; otherwise, the system terminates the program with an error message.
C
EM
Advantages:
It is the wasted space inside fixed size memory region or it can be defined as the the wastage of memory
due to size difference between partition and program loaded in it. Here the partition size may not be equal
to the program size and so some wastage of space inside a partition can occur. This free space is called
hole or internal fragment. In the example shown in below figure. the first partition size is 150KB. But the
program loaded in it used only 100KB. Therefore, there is wastage of 50KB which cannot be used by any
other process. This is called hole or internal fragments.
C
amount of space allocated to a process is the exact amount of space it requires, eliminating internal
fragmentation. In this scheme, the entire user space is treated as a “big hole”. The boundaries of the
partitions are dynamically changed, and the boundaries are depend on the size of the process. The OS
must manage more data. The exact starting and ending of each process must be stored, and data on which
memory locations are free must be maintained.
If two programs A and B of size 200 and 150 are to be executed then the partition size will
EM
be exactly 200 and 150 respectively. Therefore in this scheme, there will be no internal
fragmentation.
Advantages
● In this scheme partitions are changed dynamically. So doesn‟t suffer from internal fragmentation
● efficient memory and processor utilization
Disadvantages
● the implementation of dynamic partitioning algorithm is difficult and takes a lot of CPU time
● wastage of space due to external fragmentation:
When one or more programs finish its execution, the memory occupied by them will be freed by
the OS and those partitions are now available for program loading. But if the incoming program
size is greater than any available free partition, the program cannot be loaded to any of the
partition and hence all the partition becomes wastage. This wasted memory is called external
fragments. So External fragmentation exists when enough total memory space exists to satisfy a
request, but it is not contiguous.
At first three programs A, B and C of sizes 250,150 and 100 are loaded into memory and a free
C space of 50 is available. Suppose program B finishes its execution and leaves that 150 KB. The
next program D of size 200 cannot be loaded into memory even though a free space of 200(150 +
50) is available.
In the variable-partition scheme, 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 one large block of available memory, a hole. When a process arrives and needs memory then
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 request.
The memory blocks available comprise a set of holes of various sizes scattered throughout
memory. When a process arrives and needs memory, the system searches the set for a hole that is large
enough for this process. If the hole is too large, it is split into two parts. One part is allocated to the
arriving process; the other is returned to the set of holes. When a process terminates, it releases its block
of memory, which is then placed back in the set of holes. If the new hole is adjacent to other holes, these
adjacent holes are merged to form one larger hole.
The operating system can order the input queue according to a scheduling algorithm. Memory is allocated
to processes until, finally, the memory requirements of the next process cannot be satisfied; no available
block of memory (or hole) is large enough to hold that process. The operating system can then wait until a
large enough block is available, or it can skip down the input queue to see whether the smaller memory
requirements of some other process can be met. The free partition is then found based on either first, best
or worst fit algorithms.
● First fit: Allocate the first hole that is big enough. Searching can start either at the beginning of
the set of holes or where the previous first-fit search ended. We can stop searching as soon as we
find a free hole that is large enough.
● Best fit: Allocate the smallest hole that is big enough. We must search the entire list, unless the
list is kept ordered by size. This strategy produces the smallest leftover hole.
● Worst fit: Allocate the largest hole. Again, we must search the entire list, unless it is sorted by
size. This strategy produces the largest leftover hole, which may be more useful than the smaller
leftover hole from a best-fit approach.
Both first and best fit are better than worst fit.
4.3.3 Fragmentation
Both the first-fit and best-fit strategies for memory allocation suffer from external fragmentation. As
processes are loaded and removed from memory, the free memory space is broken into little pieces.
External fragmentation exists when there is enough total memory space to satisfy a request but the
available spaces are not contiguous: storage is fragmented into a large number of small holes. This
fragmentation problem can be severe. In the worst case, we could have a block of free (or wasted)
memory between every two processes. If all these small pieces of memory were in one big free block
instead, we might be able to run several more processes.Whether we are using the first-fit or best-fit
C
strategy can affect the amount of fragmentation. (First fit is better for some systems, whereas best fit is
better for others.) Another factor is which end of a free block is allocated.
One solution to the problem of external fragmentation is compaction. The goal is to shuffle the memory
contents so as to place all free memory together in one large block. Compaction is not always possible,
however. If relocation is static and is done at assembly or load time, compaction cannot be done. It is
possible only if relocation is dynamic and is done at execution time. If addresses are relocated
EM
dynamically, relocation requires only moving the program and data and then changing the base register to
reflect the new base address.
Another possible solution to the external-fragmentation problem is to permit the logical address space of
the processes to be noncontiguous, thus allowing a process to be allocated physical memory wherever
such memory is available. Two complementary techniques achieve this solution: segmentation and
paging.
4.4 Paging
the backing store, from which most of the previous memory-management schemes suffered. When some
code fragments or data residing in main memory need to be swapped out, space must be found on the
backing store. The fragmentation problems discussed in connection with main memory are also prevalent
with backing store, except that access is much slower, so compaction is impossible. Because of its
advantages over the previous methods, paging in its various forms is commonly used in most operating
systems.
4.4.1Basic Method
Physical memory is broken into fixed-sized blocks called frames. Logical memory is also broken into
blocks of the same size called pages. When a process is to be executed, its pages are loaded into any
available memory frames from the backing store. The backing store is divided into fixed-sized blocks that
are of the same size as the memory frames. Figure 6. Paging Hardware
C
EM
The hardware support for paging is illustrated in Figure 6. Every address generated by the CPU is divided
into two parts: a page number (p) and a page offset (d). The page number is used as an index into a page
table. The page table contains the base address of each page in physical memory. This base address is
combined with the page offset to define the physical memory address that is sent to the memory unit.
The page size (like the frame size) is defined by the hardware. The size of a page is typically a power of
2, varying between 512 bytes and 16MB per page, depending on the computer architecture. The selection
of a power of 2 as a page size makes the translation of a logical address into a page number and page
offset particularly easy. If the size of logical-address space is2m, and a page size is 2n addressing units
(bytes or words), then the high-order m - n bits of a logical address designate the page number, and the n
low-order bits designate the page offset. Thus, the logical address is as follows:
Where p is an index into the page table and d is the displacement within the page. Example, consider the
memory in Figure 8.12. Here, in the logical addressing=2and m=4.Usingapagesize of 4 bytes and a
physical memory of 32 bytes (8 pages), we show how the programmer’s view of memory can be mapped
into physical memory. Logical address 0 is page 0, offset 0. Indexing into the page table, we find that
page 0.
C
EM
Figure:8 Paging example for a 32-byte memory with 4-byte pages.
Thus, logical address 0 maps to physical address 20 [= (5×4) +0]. Logical address 3 (page 0, offset 3)
maps to physical address 23 [= (5×4) +3].