都分别进行了设置.
3.1 与内存映射相关的几个宏
这几个宏把无符号整数转换成对应的类型
#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 __pa(x) ((unsigned long)(x)-PAGE_OFFSET) | 把物理地址转化为线性地址
#define __va(x) ((void *)((unsigned long)(x) PAGE_OFFSET)) | 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)) | 根据页描述符和属性得到一个页表项值
#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) |
3.2内核页表的初始化
内核在进入保护模式前, 还没有启用分页功能, 在这之前内核要先建立一个临时内核页表,在进入保护模式后, 内核继续初始化直到建立完整的内存映射机制之前, 仍然需要用到页表来映射相应的内存地址. 临时页表的初始化是在arch/i386/kernel/head.S中进行的:swapper_pg_dir是临时页全局目录表, 它是在内核编译过程中静态初始化的.pg0是第一个页表开始的地方, 它也是内核编译过程中静态初始化的.
内核通过以下代码建立临时页表:
ENTRY(startup_32) ………… /* 得到开始目录项的索引,从这可以看出内核是在swapper_pg_dir的768个表项开始进行建立的, 其对应的线性地址就是0xc0000000以上的地 址, 也就是内核在初始化它自己的页表 */ page_pde_offset = (__PAGE_OFFSET >> 20); /* pg0地址在内核编译的时候, 已经是加上0xc0000000了, 减去0xc00000000得到对应的物理地址 */ movl $(pg0 - __PAGE_OFFSET), |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn
为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
|
|