Chapter 8 Memory Manager

advertisement
Chapter 8 Memory Manager
8.2
Virtual memory
Gray Sections 1.8 and 1.10 deal with the memory space of a process; Program 1.4 finds the
virtual addresses of variables of different types.
Maekawa deals with virtual memory Chapter 5, with considerable emphasis on algorithms.
Robbins Section 2.1 shows the layout of an executable program in memory, while Section 2.2
shows where static variables are stored.
Solomon introduces NT virtual memory in Chapter One. The NT memory manager provides
services similar to Linux.
8.6
Paging
Bowman describes the overall architecture of the Linux memory manager in Section 2.2.
Various sections in Chapter 3 of Rusling provide relevant background for this area. Section
3.2 gives an overview of the use of a translation lookaside buffer in Linux.
Section 3.3 gives an overview of page tables in Linux. Section 3.4 covers allocation and
deallocation of pages in Linux, while Section 3.7 deals with the Linux page cache.
Solomon Chapter Five deals with address translation in NT.
A virtual address on an Intel machine is interpreted as in Linux:
 The high order 10 bits index into the page directory
 the next 10 bits index into the page table
 the low order 12 bits index into the page.
Figure 5-11 gives the format of a page table entry (PTE).
NT uses a page frame database, which is implemented as an array. Each page frame can be
in one of eight states, so there are eight sets of links through this array. Page tables also
point to appropriate entries in this array.
Figure 5-18 is a state diagram for page frame transitions.
8.7
Architecture independent memory model
Rusling Section 3.1 gives an overview of Linux virtual memory. Section 3.5 covers the
architecture independent memory model, including the vm_area_struct. This is covered in
even more detail in Section 4.5.
Solomon Chapter Five deals with the address space layout in NT.
Figure 5-4 gives the layouts for the Intel architecture. The low 2 Gb is for the user; the
high 2Gb is for the operating system.
Table 5-5 is the user process address space layout.
© John O’Gorman 2000
Table 5-6 is the system process address space layout.
The NT counterpart of the vm_area_struct in Linux is the virtual address descriptor
(VAD). Each one tracks a range of virtual addresses. They are maintained as a tree, like
the Linux avl tree.
Page fault handling is also covered in this chapter.
8.8
System services for memory management
Memory mapping
Gray introduces mmap() and munmap() in Section 8.5, with an example in Program 8.6.
Haviland Section 12.3 also covers memory mapping, with an example.
Stevens deals with the mmap() system service in Section 12.9. Program 12.14 copies a file
using memory mapped I/O. Program 14.12 implements IPC between parent and child by
memory mapping the /dev/zero device.
System V shared memory
Goldt deals with System V shared memory, including some sample programs, in Chapter 6.
Gray deals with creating a shared memory segment, and shmget(), in Section 8.2. Program
8.1 illustrates this. Controlling a shared memory segment, and shmctl(), is in Section 8.3.
Then operations on a shared memory segment, using shmat() and shmdt(), are covered in
Section 8.4. Program 8.2 deals with creating, attaching, and manipulating shared memory.
An extended producer/consumer example is given, in which Program 8.3 is the parent
process, Program 8.2 is the producer, and program 8.5 is the consumer.
Haviland deals with System V shared memory, including a programming example, in Section
8.3.4.
Rusling Section 5.3.4 covers System V shared memory.
Stevens Section 14.9 deals with System V shared memory, the shmget() system service,
etc. Program 14.11 shows where different types of data (including shared) are stored in
memory.
8.9
Page replacement
Maekawa Section 5.3 deals with stack replacement algorithms.
See Rusling Section 3.8 on swapping and discarding pages in Linux.
For replacement, NT uses a version of the LRU algorithm. See Solomon Chapter Five.
© John O’Gorman 2000
8.11
Fetch policies
Anticipatory fetch policies
See Maekawa Section 5.4 on working sets.
Rusling Section 3.6 covers demand paging in Linux.
Solomon deals with working sets in NT, in Chapter Five.
NT uses demand paging, but it also uses clusters. A cluster is the faulting page, plus 0-7
pages immediately adjacent to it.
The default working set is 20 – 345 pages, depending on the size of installed memory. The
‘balance set manager’ controls this.
8.13
1.
Discussion questions
Yes, if it was not compressed, and was aligned on a page boundary.
[Section 8.1]
2. Relative addresses can only specify offsets of typically 32K backwards or forwards
from the current position. Such a scheme would not work if code and data and stack
were in different segments, as is common.
[Section 8.1]
3. Special hardware, implemented on the CPU chip, which keeps the slowdown to under
10%.
[Section 8.1]
4. Segment the programs, and build a base register into the CPU. If this is not
available, have several banks of 64K memory. The CPU can only see one of these at
a time, and the compiler would have to generate code to switch between them.
[Section 8.1]
5. Virtual memory means that the memory map as seen by the program (Logical) is
different from what actually exists in hardware (Physical). This may include
extended memory, or not.
[Section 8.2]
6. The CPU could have several pairs of base/limit registers, for code, data, and stack.
Each of these could be extended to contain protection bits. If there are several
data registers, one could be used to control a shared segment.
There could be several code (or data) segments on disk, but only one (or a few) in
memory at any given time. This would implement a form of extended memory.
[Section 8.3]
© John O’Gorman 2000
7. The system could create a fixed number of extra (spare) entries at runtime. Or it
could arrange for extra entries to be linked on to the end of the static table.
[Section 8.4]
8. 0xFDE9 is 1111 1101 1110 1001 in binary. The high order five bits are 11111. So the
segment number is 0x1F or 31 decimal.
0x213 is 0010 0001 0011 in binary. When the 11 low order bits are appended to this,
we get 001 0000 1001 1101 1110 1001,
or hexadecimal
1 0 9 D E 9.
[Section 8.4]
9. A shared segment is referenced by a pointer in the segment table. There must be
some way of indicating that this is a shared segment, and is not to be released.
One possibility is for the entry in the segment table to point to some sort of sharing
descriptor (with a reference count), and not directly to the segment. NT uses a
‘prototype pte’ for this.
[Section 8.4]
10. There must be enough swap space on disk to hold all segments or pages of all of the
running processes.
[Section 8.4]
11. It would be possible to extend each descriptor, so that there is room both for the
memory address and a disk address. It is more common to keep disk addresses in a
separate data structure.
[Section 8.4]
12. A cache entry could be extended to contain the pid of the process to which it
belongs. So it would be possible to have an entry for segment 1 of process 100, and
segment 1 of process 200, for example, at the same time.
[Section 8.5]
13. Normally not. But yes if they are sharing. For example, two processes running an
editor. There is only one physical copy of the editor, so entries in both segment
tables would point to the same physical address.
[Section 8.4]
14. Assume it is the first entry on its hash chain. The MMU must first access the hash
table, then the page table entry. So a minimum of two memory references are
required. A large program would have long hash chains, resulting in many memory
references.
[Section 8.6]
15. An advantage is that it allows for gaps in the virtual address space. It is essential
that the tree is shallow, otherwise there will be too many memory accesses per
lookup. Two (or at most three) levels is acceptable.
[Section 8.6]
© John O’Gorman 2000
16.
a) If it tries to read the next byte, there will be no corresponding page table
entry, and the memory management unit will generate an error (interrupt)
b) These will be valid reads, but the data will be undefined – probably zeroes.
[Section 8.6]
17. Figure 8.15 is the physical page table. Each valid entry in any leaf of this tree
represents a page in the virtual address space.
Figure 8.21 is a higher level view of the same virtual address space. But this does
not view it as made up of pages, but rather as regions, or blocks of valid virtual
addresses. It also contains information about what is backing each of these regions,
typically a file on disk.
The bottom row of Figure 8.21 identifies which pages of each region are actually in
physical memory. This duplicates information from Figure 8.15, but also extends it.
[Section 8.6]
18. Common code in the kernel treats page tables as if they had three levels. The extra
one, between the page directory and the page tables, is known as a page middle
directory. On the PC architecture, this is treated as having only one entry.
The functions and macros for manipulating entries in each of these pages are
defined in <asm/page.h> and <asm/pgtable.h>. So machines with a three level page
table, such as the Alpha, have different code from those with a two level page table,
such as the PC.
[Section 8.6]
19. The address of the allocated swap space is saved in the page table. This address is
a combination of a swap space number, and a page offset within that particular swap
space, to identify the page uniquely on disk. See Card Section 8.5.6.3.
[Section 8.6]
20. The function cannot know what use is going to be made of the mapped region, i.e.
whether it is int, or char, etc. So it returns a void pointer, which the user can then
cast as appropriate.
[Section 8.8]
21. By definition, exec creates a whole new address space. So it is meaningless to speak
of inheriting memory mapping across an exec. [Section 8.8]
22. It can be used to look back over reference strings of page faults. We gather the
information about the pattern of page faults first of all. Then we go back and scan
forwards over this information.
[Section 8.9]
23. The presence bit should be cleared. So a reference to this page will fault. The page
fault handler looks at this list before going to disk, and validates the page (including
setting the presence bit).
[Section 8.9]
24. For example, see Maekawa Section 5.3.
© John O’Gorman 2000
[Section 8.9]
25. The essential difference is in how a page is selected before giving the second
chance. NRU takes account of recent usage, while FIFO does not.
[Section 8.9]
26. 12567
1567
157
1567
12567
12356
12346
1234
234
34
134
1234
234
[Section 8.9]
27. A ‘has_been_swapped’ bit in the task_struct. This is set when a process is swapped.
When searching for a victim to swap out, any processes with this bit set are passed
over. This search could work through processes in order of decreasing number of
physical pages allocated.
If the system ever reaches the state where all processes have this bit set, then it
would be cleared in all of them.
[Section 8.9]
28. As it would only write pages when the disk channel is idle, it would put no extra
overhead on that channel. There would be a slight overhead of finding the page, and
setting up the I/O transfer.
There would be a definite advantage when it finally comes to removing that page.
But as there is at least a possibility that the page would be written to again soon,
this could negate any advantage.
[Section 8.9]
29. Timestamp pages when they are loaded in. Use a normal algorithm (e.g. FIFO or
LRU), but when this selects a page, if dirty AND recent, skip over it.
[Section 8.9]
30. A compiler could profile the program from the beginning (say 100,000 instructions),
and calculate the code and data pages needed for these. This information could be
stored in the header of the executable.
The exec function would have to be extended to load all of these pages, before
attempting to run the program.
[Section 8.11]
© John O’Gorman 2000
Download