Библиотека сайта rus-linux.net
The book is available and called simply "Understanding The Linux Virtual Memory Manager". There is a lot of additional material in the book that is not available here, including details on later 2.4 kernels, introductions to 2.6, a whole new chapter on the shared memory filesystem, coverage of TLB management, a lot more code commentary, countless other additions and clarifications and a CD with lots of cool stuff on it. This material (although now dated and lacking in comparison to the book) will remain available although I obviously encourge you to buy the book from your favourite book store :-) . As the book is under the Bruce Perens Open Book Series, it will be available 90 days after appearing on the book shelves which means it is not available right now. When it is available, it will be downloadable from http://www.phptr.com/perens so check there for more information.
To be fully clear, this webpage is not the actual book.
Next: 4.2 Describing a Page Up: 4. Page Table Management Previous: 4. Page Table Management   Contents   Index
4.1 Describing the Page Directory
Each process has its own Page Global Directory (PGD) which
is a physical page frame containing an array of pgd_t
,
an architecture specific type defined in asm/page.h
. The page
tables are loaded differently on each architecture. On the x86, the process
page table is loaded by copying the pointer to the PGD into the cr3
register which has the side effect of flushing the TLB. In fact this is how
the function __flush_tlb()
is implemented in the architecture
dependent code.
Each active entry in the PGD table points to a page frame containing an array
of Page Middle Directory (PMD) entries of type pmd_t
which in turn point to page frames containing Page Table Entries
(PTE) of type pte_t
, which finally point to page frames
containing the actual user data. In the event the page has been swapped
out to backing storage, the swap entry is stored in the PTE and used by
do_swap_page()
during page fault to find the swap entry
containing the page data.
Any given linear address may be broken up into parts to yield offsets within
these three page table levels and an offset within the actual page. To help
break up the linear address into its component parts, a number of macros are
provided in triplets for each page table level, namely a SHIFT
,
a SIZE
and a MASK
macro. The SHIFT
macros specifies the length in bits that are mapped by each level of the
page tables as illustrated in Figure 4.1.
The MASK
values can be ANDd with a linear address to mask out
all the upper bits and are frequently used to determine if a linear address
is aligned to a given level within the page table. The SIZE
macros reveal how many bytes are addressed by each entry at each level.
The relationship between the SIZE
and MASK
macros
is illustrated in Figure 4.2.
For the calculation of each of the triplets, only SHIFT
is
important as the other two are calculated based on it. For example, the
three macros for page level on the x86 are:
5 #define PAGE_SHIFT 12 6 #define PAGE_SIZE (1UL << PAGE_SHIFT) 7 #define PAGE_MASK (~(PAGE_SIZE-1))
PAGE_SHIFT
is the length in bits of the offset part of
the linear address space which is 12 bits on the x86. The size of a page is
easily calculated as
which is the equivalent of
the code above. Finally the mask is calculated as the negation of the bits
which make up the PAGE_SIZE - 1
. If a page needs to be aligned
on a page boundary, PAGE_ALIGN()
is used. This macro adds
PAGE_SIZE - 1
is added to the address before simply ANDing it
with the PAGE_MASK
.
PMD_SHIFT
is the number of bits in the linear address which
are mapped by the second level part of the table. The PMD_SIZE
and PMD_MASK
are calculated in a similar way to the page
level macros.
PGDIR_SHIFT
is the number of bits which are mapped by
the top, or first level, of the page table. The PGDIR_SIZE
and PGDIR_MASK
are calculated in the same manner as above.
The last three macros of importance are the PTRS_PER_x
which determine the number of entries in each level of the page
table. PTRS_PER_PGD
is the number of pointers in the PGD,
1024 on an x86 without PAE. PTRS_PER_PMD
is for the PMD,
1 on the x86 without PAE and PTRS_PER_PTE
is for the lowest
level, 1024 on the x86.
Next: 4.2 Describing a Page Up: 4. Page Table Management Previous: 4. Page Table Management   Contents   Index Mel 2004-02-15