【转】与内存管理相关的几个宏
这几个宏把无符号整数转换成对应的类型
#define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
根据x把它转换成对应的无符号整数
#define pte_val(x) ((x).pte_low)
#define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
与下一个页框对齐
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
把内核空间的线性地址转换为物理地址
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
把物理地址转化为线性地址
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
首先把pfn页框号转化为内核线性地址, 然后左移12位, 得到对应的内核线性地址
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
根据页框号得到对应的物理页描述符
#define pfn_to_page(pfn) (mem_map + (pfn))
根据物理描述符得到对应的页框号
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
根据内核线性地址得到其对应的物理页描述符
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
清除一个页表项并返回前一个值
#define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte_low, 0))
判断一个页表项是否指向同一页并且访问优先级相同
#define pte_same(a, b) ((a).pte_low == (b).pte_low)
x是页表项值, 通过pte_pfn得到其对应的物理页框号, 最后通过pfn_to_page得到对应的物理页描述符
#define pte_page(x) pfn_to_page(pte_pfn(x))
如果对应的表项值为0, 返回1
#define pte_none(x) (!(x).pte_low)
x是页表项值, 右移12位后得到其对应的物理页框号
#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
根据页框号和页表项的属性值合并成一个页表项值
#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
根据页框号和页表项的属性值合并成一个中间表项值
#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
向一个表项中写入指定的值
#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
#define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
根据线性地址得到高10位值, 也就是在目录表中的索引
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
根据mm和线性地址address得到目录项值
#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
根据线性地址address提取在页表中的索引
#define pte_index(address)
(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
根据页描述符和属性得到一个页表项值
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))
#define __pte(x) ((pte_t) { (x) } )
#define __pmd(x) ((pmd_t) { (x) } )
#define __pgd(x) ((pgd_t) { (x) } )
#define __pgprot(x) ((pgprot_t) { (x) } )
根据x把它转换成对应的无符号整数
#define pte_val(x) ((x).pte_low)
#define pmd_val(x) ((x).pmd)
#define pgd_val(x) ((x).pgd)
#define pgprot_val(x) ((x).pgprot)
与下一个页框对齐
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
把内核空间的线性地址转换为物理地址
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
把物理地址转化为线性地址
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
首先把pfn页框号转化为内核线性地址, 然后左移12位, 得到对应的内核线性地址
#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT)
根据页框号得到对应的物理页描述符
#define pfn_to_page(pfn) (mem_map + (pfn))
根据物理描述符得到对应的页框号
#define page_to_pfn(page) ((unsigned long)((page) - mem_map))
根据内核线性地址得到其对应的物理页描述符
#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
清除一个页表项并返回前一个值
#define ptep_get_and_clear(xp) __pte(xchg(&(xp)->pte_low, 0))
判断一个页表项是否指向同一页并且访问优先级相同
#define pte_same(a, b) ((a).pte_low == (b).pte_low)
x是页表项值, 通过pte_pfn得到其对应的物理页框号, 最后通过pfn_to_page得到对应的物理页描述符
#define pte_page(x) pfn_to_page(pte_pfn(x))
如果对应的表项值为0, 返回1
#define pte_none(x) (!(x).pte_low)
x是页表项值, 右移12位后得到其对应的物理页框号
#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT)))
根据页框号和页表项的属性值合并成一个页表项值
#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
根据页框号和页表项的属性值合并成一个中间表项值
#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
向一个表项中写入指定的值
#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
#define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
根据线性地址得到高10位值, 也就是在目录表中的索引
#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
根据mm和线性地址address得到目录项值
#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
根据线性地址address提取在页表中的索引
#define pte_index(address)
(((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
根据页描述符和属性得到一个页表项值
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot))