Vous êtes sur la page 1sur 7

Chapter 7 Unit 3

1 | P a g e

Chapter 7
Memory Management


7.1 Concepts
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 memory
according to the value of the program counter. These instructions may cause additional loading
from and storing to specific memory addresses. A typical instruction-execution cycle, for
example, first fetches an instruction from memory. The instruction is then decoded and may
cause operands to be fetched from memory. After the instruction has been executed on the
operands, results may be stored back in memory. The memory unit sees only a stream of memory
addresses; it does not know how they are generated (by the instruction counter, indexing,
indirection, literal addresses, and so on) or what they are for (instructions or data). Accordingly,
we can ignore how a program generates a memory address. We are interested only in the
sequence of memory addresses generated by the running program.

7.2 Logical and physical address space
An address generated by the CPU is commonly referred to as a logical address, whereas an
address seen by the memory unitthat is, the one loaded into the memory-address register of the
memoryis commonly referred 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. 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. The run-time mapping from
virtual to physical addresses is done by a hardware device called the memory-management unit
(MMU).

7.3 Address Binding
A program resides on a disk as a binary executable file. To be executed, the program must be
brought into memory and placed within a process. Depending on the memory management in
use, the process may be moved between disk and memory during its execution. The processes on
the disk that are waiting to be brought into memory for execution form 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. 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 need not be 00000. This approach
affects the addresses that the user program can use. In most cases, a user program will go
through several stepssome of which maybe optional-before being executed. 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
Chapter 7 Unit 3

2 | P a g e

or loader will in turn bind the relocatable addresses to absolute addresses (such as 74014). Each
binding is a mapping from one address space to another. Classically, the binding of instructions
and data to memory addresses can be done at any step along the way:

Compile time. If you know at compile time where the process will reside in memory, then
absolute code can be generated. For example, if you know that a user process will reside starting
at location R, then the generated compiler code will start at that location and extend up from
there. If, at some later time, the starting location changes, then it will be necessary to recompile
this code.

Load time. 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 reload the user code to incorporate this changed
value.

Execution time. If the process can be moved during its execution from one memory segment to
another, then binding must be delayed until run time. Special hardware must be available for this
scheme to work.

7.4 Degree of multiprogramming
When multiprogramming is used, the CPU utilization can be improved. Crudely put, if the
average process computes only 20 percent of the time it is sitting in memory, with five processes
in memory at once, the CPU should be busy all the time. This model is unrealistically optimistic,
however, since it assumes that all five processes will never be waiting for I/O at the same time.
A better model is to look at CPU usage from a probabilistic viewpoint. Suppose that a process
spends a fraction p of its time waiting for I/O to complete. With n processes in memory at once,
the probability that all n processes are waiting for I/O (in which case the CPU will be idle) is p
n
.
The CPU utilization is then given by the formula
CPU utilization = 1 p
n

Figure 7.1 shows the CPU utilization as a function of n which is called the degree of
multiprogramming.

Figure 7.1: CPU utilization as a function of the number of processes in memory
Chapter 7 Unit 3

3 | P a g e

From the figure it is clear that if processes spend 80 percent of their time waiting for I/O, at least
10 processes must be in memory at once to get the CPU waste below 10 percent.

7.5 Swapping
A process must 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 another process into the memory space that has been freed as shown in
Figure 7.2. 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.
Ideally, the memory manager can swap processes fast enough that some processes will be in
memory, ready to execute, when the CPU scheduler wants to reschedule the CPU. In addition,
the quantum must be large enough to allow reasonable amounts of computing to be done
between swaps.











Figure 7.2: Swapping of two processes using a disk as a backing store.

7.6 Dynamic loading
The entire program and all data of a process must be in physical memory for the process to
execute. The size of a process is thus 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 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.


Chapter 7 Unit 3

4 | P a g e

7.7 Dynamic linking and shared 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. Here, though,
linking, rather than loading, is postponed until execution time. This feature is usually used with
system libraries, such as language subroutine libraries. Without this facility, each program on a
system must include a copy of its language library (or at least the routines referenced by the
program) in the executable image. This requirement wastes both disk space and main memory.
With dynamic linking, a stub is included in the image for each library routine reference. The 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 the stub is executed,
it checks to see whether the needed routine is already in memory. If not, the program loads the
routine into memory. Either way, the stub replaces itself with the address of the routine and
executes the routine. Thus, the next time that particular 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. This feature can
be extended to library updates (such as bug fixes). 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. Unlike dynamic loading, dynamic linking generally requires help from
the operating system. If the processes in memory are protected from one another, then the
operating system is the only entity that can check to see whether the needed routine is in another
process's memory space or that can allow multiple processes to access the same memory
addresses.

7.8 Free space management
7.8.1 Memory Management with Bitmaps
When memory is assigned dynamically, the operating system must manage it. In general terms,
there are two ways to keep track of memory usage: bitmaps and free lists. With a bitmap,
memory is divided up into allocation units, perhaps as small as a few words and perhaps as large
as several kilobytes. Corresponding to each allocation unit is a bit in the bitmap, which is 0 if the
unit is free and 1 if it is occupied (or vice versa). Figure 7.3 shows part of memory and the
corresponding bitmap.






Chapter 7 Unit 3

5 | P a g e


Figure 7.3: (a) A part of memory with five processes and three holes. The tick marks
show the memory allocation units. The shaded regions (0 in the bitmap) are free. (b)
The corresponding bitmap. (c) The same information as a list.

A bitmap provides a simple way to keep track of memory words in a fixed amount of memory
because the size of the bitmap depends only on the size of memory and the size of the allocation
unit. The main problem with it is that when it has been decided to bring a k unit process into
memory, the memory manager must search the bitmap to find a run of k consecutive 0 bits in the
map. Searching a bitmap for a run of a given length is a slow operation.

7.8.2 Memory Management with Linked Lists
Another way of keeping track of memory is to maintain a linked list of allocated and free
memory segments, where a segment is either a process or a hole between two processes. The
memory of Figure 7.3(a) is represented in Figure 7.3(b) as a linked list of segments. Each entry
in the list specifies a hole (H) or process (P), the address at which it starts, the length, and a
pointer to the next entry.
In this example, the segment list is kept sorted by address. Sorting this way has the advantage
that when a process terminates or is swapped out, updating the list is a simple task.

7.9 Memory allocation schemes
First fit: 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.
2. Next fit: A minor variation of first fit is next fit. It works the same way as first fit, except that
it keeps track of where it is whenever it finds a suitable hole. The next time it is called to find a
hole, it starts searching the list from the place where it left off last time, instead of always at the
beginning, as first fit does.
3. Best fit: Best fit allocate the smallest hole that is big enough. We must search the entire list,
unless the list is ordered by size. This strategy produces the smallest leftover hole.
4. Worst fit: 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.
Chapter 7 Unit 3

6 | P a g e

5. Quick fit: Yet another allocation algorithm is quick fit, which maintains separate lists for
some of the more common sizes requested. For example, it might have a table with n entries, in
which the first entry is a pointer to the head of a list of 4-KB holes, the second entry is a pointer
to a list of 8-KB holes, the third entry a pointer to 12-KB holes, and so on. Holes of say, 21 KB,
could either be put on the 20-KB list or on a special list of odd-sized holes. With quick fit,
finding a hole of the required size is extremely fast, but it has the same disadvantage as all
schemes that sort by hole size, namely, when a process terminates or is swapped out finding its
neighbors to see if a merge is possible is expensive. If merging is not done, memory will quickly
fragment into a large number of small holes into which no processes fit.

As an example of first fit, best fit and worst fit, consider the above Figure 7.3. If a block of size 2
is needed, first fit will allocate the hole at 5, but best fit will allocate the hole at 18, the worst fit
can allocate the hole at 5 or at 29.


7.10 Buddys system
The "buddy system" allocates memory from a fixed-size segment consisting of physically
contiguous pages. Memory is allocated from this segment using a power-of-2 allocator, which
satisfies requests in units sized as a power of 2 (4 KB, 8 KB, 16 KB, and so forth). A request in
units not appropriately sized is rounded up to the next highest power of 2. For example, if a
request for 11 KB is made, it is satisfied with a 16-KB segment.
Example: Let's assume the size of a memory segment is initially 256 KB and the kernel requests
21 KB of memory. The segment is initially divided into two buddieswhich we will call A
L
and
A
R
each 128 KB in size. One of these buddies is further divided into two 64-KB buddiesB
L

and B
R
. However, the next-highest power of 2 from 21 KB is 32 KB so either B
L
or B
R
is again
divided into two 32-KB buddies, C
L
and C
R
. One of these buddies is used to satisfy the 21-KB
request. This scheme is illustrated in Figure 7.4, where C
L
is the segment allocated to the 21 KB
request.

Figure 7.4: Buddy system allocation

Chapter 7 Unit 3

7 | P a g e

An advantage of the buddy system is how quickly adjacent buddies can be combined to form
larger segments using a technique known as coalescing. for example, when the kernel releases
the C
L
unit it was allocated, the system can coalesce C
L
and C
R
into a 64-KB segment. This
segment, B
L
, can in turn be coalesced with its buddy B
R
to form a 128-KB segment. Ultimately,
we can end up with the original 256-KB segment. The obvious drawback to the buddy system is
that rounding up to the next highest power of 2 is very likely to cause fragmentation within
allocated segments. For example, a 33-KB request can only be satisfied with a 64-KB segment.
In fact, we cannot guarantee that less than 50 percent of the allocated unit will be wasted due to
internal fragmentation

7.11 Memory protection
We can provide this feature by using a relocation register, with a limit register. The relocation
register contains the value of the smallest physical address; the limit register contains the range
of logical addresses (for example, relocation = 100040 and limit = 74600). With relocation and
limit registers, each logical address must be less than the limit register; the VIMU maps the
logical address dynamically by adding the value in the relocation register. This mapped address
is sent to memory. When the CPU scheduler selects a process for execution, the dispatcher loads
the relocation and limit registers with the correct values as part of the context switch. Because
every address generated by the CPU is checked against these registers, we can protect both the
operating system and the other users' programs and data from being modified by this running
process. The relocation-register scheme provides an effective way to allow the operating-system
size to change dynamically. This flexibility is desirable in many situations. For example, the
operating system contains code and buffer space for device drivers. If a device driver (or other
operating-system service) is not commonly used, we do not want to keep the code and data in
memory, as we might be able to use that space for other purposes. Such code is sometimes called
transient operating-system code; it comes and goes as needed. Thus, using this code changes the
size of the operating system during program execution.

Vous aimerez peut-être aussi