免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4540 | 回复: 5
打印 上一主题 下一主题

关于linux内存初始化的几个疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-23 18:12 |只看该作者 |倒序浏览
最近研究下linux的内存管理机制,总体上来说,虽然内存管理比较繁琐,但思想还是比较容易掌握,只是在内存管理初始化的时候,有几个问题,理解的时候有困惑,希望路过的牛人们指点一二:


1.系统启动之初,尚未开启分页机制,内核映像会被加载到1MB开始的物理内存处,此时会建立临时的页表,为了后面开启分页机制之用,而且根据资料叙述,好像这个临时的页目录表swapout_dir是被安放在物理内存1MB+4KB的位置,在页目录表之上是2个页表,pg0和pg1,用来映射物理地址0~8MB的空间。我的理解是否正确??

2.在内存管理使用伙伴系统之前,Linux使用了一种叫bootmem分配器(bootmem allocator)的机制,它为整个物理内存建立起一个页面位图,这里的疑问是:这个页面位图到底存放在物理内存的什么地方?紧接着1中设置的pg1存放?建立起来的页面位图中包含了所有物理的内存信息,而且在此之后会将一些物理页面设置为保留,具体哪些物理页面会被设置为保留?(是不是内核映像+页目录表+pg0,pg1两个页表+页面位图占据的空间?)

3.完成上面2的内存信息统计之后,会进行物理页面的映射,将所有的物理页面映射到内核空间中(3G~4G的地址空间),因为前面已经映射了0~8MB的物理地址空间,在这里的时候会不会被重新映射?

非常感谢各位,希望大家能解决我的困惑

论坛徽章:
0
2 [报告]
发表于 2011-10-23 23:07 |只看该作者
支持一下先,

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
3 [报告]
发表于 2011-10-24 11:01 |只看该作者
回复 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起始位置了。定义如下:
  1. /*
  2. * BSS section
  3. */
  4. .section ".bss.page_aligned","wa"
  5.         .align PAGE_SIZE_asm
  6. ENTRY(swapper_pg_dir)
  7.         .fill 1024,4,0
  8. ENTRY(swapper_pg_pmd)
  9.         .fill 1024,4,0
  10. ENTRY(empty_zero_page)
  11.         .fill 4096,1,0
复制代码
2.在内存管理使用伙伴系统之前,Linux使用了一种叫bootmem分配器(bootmem allocator)的机制,它为整个物理内存建立起一个页面位图,

这里的疑问是:这个页面位图到底存放在物理内存的什么地方?紧接着1中设置的pg1存放?建立起来的页面位图中包含了所有物理的内存信

息,而且在此之后会将一些物理页面设置为保留,具体哪些物理页面会被设置为保留?(是不是内核映像+页目录表+pg0,pg1两个页表+页面位

图占据的空间?)

bootmem放在内核加载位置之后。被保留的页包括:内核使用的页、bootmem自己使用的页、特定体系机构需要保留的页,至于精确的那些页

,在x86中可以通过BIOS支持。

3.完成上面2的内存信息统计之后,会进行物理页面的映射,将所有的物理页面映射到内核空间中(3G~4G的地址空间),因为前面已经映射了

0~8MB的物理地址空间,在这里的时候会不会被重新映射?

会重新映射。代码如下:
  1. static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
  2. {
  3.         unsigned long pfn;
  4.         pgd_t *pgd;
  5.         pmd_t *pmd;
  6.         pte_t *pte;
  7.         int pgd_idx, pmd_idx, pte_ofs;

  8.         pgd_idx = pgd_index(PAGE_OFFSET);
  9.         pgd = pgd_base + pgd_idx;
  10.         pfn = 0;

  11.         for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
  12.                 pmd = one_md_table_init(pgd);
  13.                 if (pfn >= max_low_pfn)
  14.                         continue;
  15.                 for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
  16.                         unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;

  17.                         /* Map with big pages if possible, otherwise create normal page tables. */
  18.                         if (cpu_has_pse) {
  19.                                 unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
  20.                                 if (is_kernel_text(address) || is_kernel_text(address2))
  21.                                         set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
  22.                                 else
  23.                                         set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));

  24.                                 pfn += PTRS_PER_PTE;
  25.                         } else {
  26.                                 pte = one_page_table_init(pmd);

  27.                                 for (pte_ofs = 0;
  28.                                      pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn;
  29.                                      pte++, pfn++, pte_ofs++, address += PAGE_SIZE) {
  30.                                         if (is_kernel_text(address))
  31.                                                 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
  32.                                         else
  33.                                                 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
  34.                                 }
  35.                         }
  36.                 }
  37.         }
  38. }
复制代码
个人观点,如有不对,欢迎指正。

论坛徽章:
0
4 [报告]
发表于 2011-10-24 19:34 |只看该作者
回复 3# 瀚海书香

首先,非常感谢斑竹的解答。看完你的解答后我还有两个疑问:

1.bootmem占用的物理空间是从什么地方开始?是不是紧接着swapper_dir_pg和pg0+pg1的这些页面存放?

2.既然在初始已经映射了0~8MB的物理地址空间,为什么还要在函数kernel_physical_mapping_init()中重新映射这8MB的空间呢?

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
5 [报告]
发表于 2011-10-24 19:48 |只看该作者
1.bootmem占用的物理空间是从什么地方开始?是不是紧接着swapper_dir_pg和pg0+pg1的这些页面存放?

2.既然在初始已经映射了0~8MB的物理地址空间,为什么还要在函数kernel_physical_mapping_init()中重新映射这8MB的空间呢?
回复 4# Tracymacding


  1.bootmem在内核加载位置之后,也就是0x10000+kernel_code+kernel_data+kernel_bss。确切的说应该在_end处。
  2. 本身前8M的映射就是一个简单的物理偏移,重新映射也不麻烦啊。

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
6 [报告]
发表于 2011-10-25 08:41 |只看该作者
本帖最后由 embeddedlwp 于 2011-10-25 08:43 编辑
bootmem放在内核加载位置之后。被保留的页包括:内核使用的页、bootmem自己使用的页、特定体系机构需要保留的页,至于精确的那些页

,在x86中可以通过BIOS支持。



我看的是Linux 2.6.11,bootmem 的bitmap放在_end之后的那个页,在bootmem初始化完自己后,保留了kernel镜像占的page,bitmap占的page,大小为 (end_pfn-start_pfn+7)/8,page 0(第一个page,而不是pg0),特定体系机构需要保留的页。

在bootmem把page交由buddy system接管时,bootmem 的bitmap占用的空间会被释放,kernel镜像占的page,page 0(第一个page,而不是pg0),特定体系机构需要保留的页仍然会被保留。bootmem的代码和数据全部被释放,可以看一下bootmem 的所有函数前都有 __init。


哪里不正确欢迎指正!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP