内存管理相关的
1.1 p
1.1 pte_offset_kernel
pte = pte_offset_kernel(pmd, vaddr);
//页目录项的某一项的线性地址,
//
//
//
#define pte_offset_kernel(dir, address) \
((pte_t *) pmd_page_kernel(*(dir)) + pte_index(address))
// dir就是页目录项其中一项的线性地址。*(dir)就是页目录项中存储的页表物理地址加上12位属性值
// ((pte_t *) pmd_page_kernel(*(dir)) 就是这个页目录项指向的页表的基地址(线性地址)加上address在页中偏移量。
// 这个函数的作用就是 找出address所属的页地址。
// 比如address=0xffff4000 dir=0xc03cbffc *dir=0x44a007
// pte_index(address)=0x3f4 pmd_page_kernel(*dir)=0xC044 a000
// pte_offset_kernel(dir, address)=0xC044 a000+0x3f4*sizeof(unsigned long)=0xC044 afd0
// 这个函数,就是根据address所属的页目录项的地址,以及address,找出存储address所属的页的基地址
// 在使用这个函数前需要,找出address所属的页目录项的地址。
#define pmd_page_kernel(pmd) \
((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
//pmd也就是页目录存的,页表的物理的前20位,加上12位的属性
//这个函数就是把页目录项中,存的页表地址,先去掉12位属性,然后通过__va转换成线性地址
335 #define pte_index(address) \
336 (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
找出地址所属的页地址,在页表中的偏移量。
例子
284 pgd = swapper_pg_dir + pgd_index(vaddr);
285 pud = pud_offset(pgd, vaddr);
286 pmd = pmd_offset(pud, vaddr);
287 pte = pte_offset_kernel(pmd, vaddr);
pgd_index
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
就是取去虚拟地址的高10位(i386)
pgd_offset/pud_offset/pmd_offset
#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
取出结构体中pgd指针,然后加上偏移量。
例子:
如果:
mm->pgd=0xc03cb000 address=0xffff4000
则:
pgd_index(address)=0x3ff
pgd_offset(mm, address)=0xc03cb000+0x3ff*4=0xc03cbffc
因为pgd是unsigned long指针,所以结果要乘以4
36 static inline pud_t * pud_offset(pgd_t * pgd, unsigned long address)
37 {
38 return (pud_t *)pgd;
39 }
说明:直接返回参数
39 static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
40 {
41 return (pmd_t *)pud;
42 }
说明:直接返回参数。