LINUX内存管理之页式管理之页表项标记位的理解

页表项的高20位指向内存页基址,低12位设置页面状态和权限。

如果页表项的present位为1,表示对应的页或者页表已经载入到内存页框。反之,如果为0,对此页的访问会触发缺页异常。而缺页异常处理函数会生成配套的页或者页表,并刷新present标记位为1。

typedef struct { unsigned long pte_low; } pte_t;
typedef struct { unsigned long pgd; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;

//获取写标志位;从字面理解以为是写操作呢,囧
static inline int pte_write(pte_t pte)      { return (pte).pte_low & _PAGE_RW; }

#define pte_present(x)  ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))

//深入理解linux内核p65里面介绍的页目录项和页表项里面的字段
#define _PAGE_PRESENT   0x001
#define _PAGE_RW    0x002
#define _PAGE_USER  0x004
#define _PAGE_PWT   0x008
#define _PAGE_PCD   0x010
#define _PAGE_ACCESSED  0x020
#define _PAGE_DIRTY 0x040

对于PAE模式来说,长度变成了64
#ifdef CONFIG_X86_PAE
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;

//获取addr在页全局目录表的索引
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
//线性地址在pgd里面的对应的线性地址
#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
//内核页全局目录某个项的线性地址
#define pgd_offset_k(address) pgd_offset(&init_mm, address)
//找到页描述符地址
#define pgd_page(pgd)               (pud_page((pud_t){ pgd }))
    =>#define pud_page(pud)             (pmd_page((pmd_t){ pud }))
        =>#define pmd_page(pmd) (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
            =>#define pfn_to_page __pfn_to_page
                =>#define __pfn_to_page(pfn)    (mem_map + ((pfn) - ARCH_PFN_OFFSET))

Linux内核中的内存管理浅谈 https://blog.csdn.net/acs713/article/details/8575421

你可能感兴趣的:(linux内核)