- 论坛徽章:
- 6
|
回复 1# Tracymacding
1.系统启动之初,尚未开启分页机制,内核映像会被加载到1MB开始的物理内存处,此时会建立临时的页表,为了后面开启分页机制之用,而
且根据资料叙述,好像这个临时的页目录表swapout_dir是被安放在物理内存1MB+4KB的位置,在页目录表之上是2个页表,pg0和pg1,用来映
射物理地址0~8MB的空间。我的理解是否正确??
你这儿的swapout_dir,应该是swapper_pg_dir。在之前的内核中好像是固定在内核加载位置+偏移0x1000,比如内核加载在0x100000,那么
swapper_pg_dir=0x101000。后来内核不知从那个版本就改动了,比如2.6.24内核中,swapper_pg_dir放在了bss起始位置了。定义如下:- /*
- * BSS section
- */
- .section ".bss.page_aligned","wa"
- .align PAGE_SIZE_asm
- ENTRY(swapper_pg_dir)
- .fill 1024,4,0
- ENTRY(swapper_pg_pmd)
- .fill 1024,4,0
- ENTRY(empty_zero_page)
- .fill 4096,1,0
复制代码 2.在内存管理使用伙伴系统之前,Linux使用了一种叫bootmem分配器(bootmem allocator)的机制,它为整个物理内存建立起一个页面位图,
这里的疑问是:这个页面位图到底存放在物理内存的什么地方?紧接着1中设置的pg1存放?建立起来的页面位图中包含了所有物理的内存信
息,而且在此之后会将一些物理页面设置为保留,具体哪些物理页面会被设置为保留?(是不是内核映像+页目录表+pg0,pg1两个页表+页面位
图占据的空间?)
bootmem放在内核加载位置之后。被保留的页包括:内核使用的页、bootmem自己使用的页、特定体系机构需要保留的页,至于精确的那些页
,在x86中可以通过BIOS支持。
3.完成上面2的内存信息统计之后,会进行物理页面的映射,将所有的物理页面映射到内核空间中(3G~4G的地址空间),因为前面已经映射了
0~8MB的物理地址空间,在这里的时候会不会被重新映射?
会重新映射。代码如下:- static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
- {
- unsigned long pfn;
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
- int pgd_idx, pmd_idx, pte_ofs;
- pgd_idx = pgd_index(PAGE_OFFSET);
- pgd = pgd_base + pgd_idx;
- pfn = 0;
- for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
- pmd = one_md_table_init(pgd);
- if (pfn >= max_low_pfn)
- continue;
- for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
- unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;
- /* Map with big pages if possible, otherwise create normal page tables. */
- if (cpu_has_pse) {
- unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
- if (is_kernel_text(address) || is_kernel_text(address2))
- set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
- else
- set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
- pfn += PTRS_PER_PTE;
- } else {
- pte = one_page_table_init(pmd);
- for (pte_ofs = 0;
- pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;
- pte++, pfn++, pte_ofs++, address += PAGE_SIZE) {
- if (is_kernel_text(address))
- set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
- else
- set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
- }
- }
- }
- }
- }
复制代码 个人观点,如有不对,欢迎指正。 |
|