页目录描述(Describing the Page Directory)
每一个进程都有一个指针指向它自己的PGD(Page Global Directory),PGD是一个物理页框。该页框包含有一组类型为pgd_t的结构。该类型有具体的架构代码中指定。例如在x86下,其定义如下:
typedef struct { unsigned long long pgd; } pgd_t;
typedef struct { unsigned long pte_low, pte_high; } pte_t;
typedef struct { unsigned long long pmd; } pmd_t;
每种架构加载page tables的方式有所不同。例如x86架构下,每个进程的page tables是通过复制mm_struct->pgd到cr3寄存器进行加载的。
PGD中的每一个active项都对应着一个物理页框,该页框包含一组PMD(Page Middle Directory)其类型为pmd_t。
PMD对应的又是一个物理页框,PMD页框中时一组PTE(Page Table Entries)其类型为pte_t,
PTE对应一个物理页框用于存放最终的数据。
一条线性地址可能被切割为多个部分形成多级页表和页内偏移。为了帮助线性地址的切割,为每一级也定义了一个宏:
/* PAGE_SHIFT determines the page size */
#define PAGE_SHIFT 12
#define PAGE_SIZE (1UL << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
页表项描述(Describing a Page Table Entry)
如上面所描述,struct pte_t,pmd_t,pgd_t分别描述PTE,PMD,PGD。尽管它们通常是一个非负整数,但是它们仍然被定义成结构体有以下两种原因:
- 为了类型保护,因此避免它们被人不合时宜的误用
- 为了支持x86的PAE功能,因为PAE有多处4个bit来描述大于4GB的memory
从下面的定义来看,分别有两种定义:
#ifdef CONFIG_X86_PAE
extern unsigned long long __supported_pte_mask;
extern int nx_enabled;
typedef struct { unsigned long pte_low, pte_high; } pte_t;
typedef struct { unsigned long long pmd; } pmd_t;
typedef struct { unsigned long long pgd; } pgd_t;
typedef struct { unsigned long long pgprot; } pgprot_t;
#define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
#define HPAGE_SHIFT 21
#else
#define nx_enabled 0
typedef struct { unsigned long pte_low; } pte_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;
#define boot_pte_t pte_t /* or would you rather have a typedef */
#define pte_val(x) ((x).pte_low)
#define HPAGE_SHIFT 22
#endif
资料直通车:最新Linux内核源码资料文档+视频资料
内核学习地址: