e820与内存探测.docx_第1页
e820与内存探测.docx_第2页
e820与内存探测.docx_第3页
e820与内存探测.docx_第4页
e820与内存探测.docx_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

e820与kernel物理内存映射deltamaster posted 大约 1 年前 in kernel with tags linux kernel RAM , 1435 阅读我们都对操作系统如何管理内存有一定的了解,然而,在操作系统开始管理内存之前,首先要获取物理内存的信息,比如一共有多少物理地址是可用的,有哪些物理地址是被ACPI(Advanced Configuration and Power Interface)数据使用,这些信息从何而来呢?e820就是BIOS像x86架构(包括x86_64)上的操作系统引导程序提供物理内存信息的功能。当请求BIOS中断号15H,并且置操作码AX=E820H的时候,BIOS就会向调用者报告可用的物理地址区间等信息,e820由此得名。Linux内核也通过这种机制来获得物理地址信息,使用dmesg可以看到相关的信息:?123456789101112131415161718192021222324252627282930 0.000000 BIOS-provided physical RAM map: 0.000000 BIOS-e820: 0000000000000000 - 000000000009e800 (usable) 0.000000 BIOS-e820: 000000000009e800 - 00000000000a0000 (reserved) 0.000000 BIOS-e820: 00000000000e0000 - 0000000000100000 (reserved) 0.000000 BIOS-e820: 0000000000100000 - 0000000020000000 (usable) #511MB 0.000000 BIOS-e820: 0000000020000000 - 0000000020200000 (reserved) 0.000000 BIOS-e820: 0000000020200000 - 0000000040000000 (usable) #510MB 0.000000 BIOS-e820: 0000000040000000 - 0000000040200000 (reserved) 0.000000 BIOS-e820: 0000000040200000 - 00000000aac0d000 (usable) #1706MB 0.000000 BIOS-e820: 00000000aac0d000 - 00000000aad8e000 (reserved) 0.000000 BIOS-e820: 00000000aad8e000 - 00000000aad95000 (usable) 0.000000 BIOS-e820: 00000000aad95000 - 00000000aad96000 (reserved) 0.000000 BIOS-e820: 00000000aad96000 - 00000000aad97000 (usable) 0.000000 BIOS-e820: 00000000aad97000 - 00000000aadb8000 (reserved) 0.000000 BIOS-e820: 00000000aadb8000 - 00000000aadc6000 (usable) 0.000000 BIOS-e820: 00000000aadc6000 - 00000000aade8000 (reserved) 0.000000 BIOS-e820: 00000000aade8000 - 00000000aaf23000 (usable) 0.000000 BIOS-e820: 00000000aaf23000 - 00000000aafe8000 (ACPI NVS) 0.000000 BIOS-e820: 00000000aafe8000 - 00000000aaffd000 (usable) 0.000000 BIOS-e820: 00000000aaffd000 - 00000000ab000000 (ACPI data) 0.000000 BIOS-e820: 00000000ab000000 - 00000000b0000000 (reserved) 0.000000 BIOS-e820: 00000000e0000000 - 00000000e4000000 (reserved) 0.000000 BIOS-e820: 00000000fec00000 - 00000000fec01000 (reserved) 0.000000 BIOS-e820: 00000000fed10000 - 00000000fed14000 (reserved) 0.000000 BIOS-e820: 00000000fed18000 - 00000000fed1a000 (reserved) 0.000000 BIOS-e820: 00000000fed1c000 - 00000000fed20000 (reserved) 0.000000 BIOS-e820: 00000000fee00000 - 00000000fee01000 (reserved) 0.000000 BIOS-e820: 00000000ff980000 - 00000000ffc00000 (reserved) 0.000000 BIOS-e820: 00000000ffd80000 - 0000000100000000 (reserved) 0.000000 BIOS-e820: 0000000100000000 - 000000014f800000 (usable) #1272MB上面是我在自己计算机上得到的数据,其中usable的区间就是实际被映射到物理内存上的地址空间,上面标注出来的四个区间,就是我主要的四个可用的物理地址区间了,大约4GB。Usable:已经被映射到物理内存的物理地址。Reserved:这些区间是没有被映射到任何地方,不能当作RAM来使用,但是kernel可以决定将这些区间映射到其他地方,比如PCI设备。通过检查/proc/iomem这个虚拟文件,就可以知道这些reserved的空间,是如何进一步分配给不同的设备来使用了。ACPI data:映射到用来存放ACPI数据的RAM空间,操作系统应该将ACPI Table读入到这个区间内。ACPI NVS:映射到用来存放ACPI数据的非易失性存储空间,操作系统不能使用。Unusable:表示检测到发生错误的物理内存。这个在上面例子里没有,因为比较少见。内核读到这些信息后,将其保存在e820map结构体中,有两个副本,一个符号名叫e820,还有一个符号名叫e820_saved。具体的数据结构可以参考arch/x86/include/asm/e820.h。随着内核的启动,内核还会修改e820的信息。?123 0.000000 e820 update range: 0000000000000000 - 0000000000010000 (usable) = (reserved) 0.000000 e820 remove range: 00000000000a0000 - 0000000000100000 (usable) 0.000000 e820 update range: 00000000ab000000 - 0000000100000000 (usable) = (reserved)比如在我的系统上发生了这样三次e820的改动,这些改动已经与BIOS没有任何关系了,只是内核自己通过修改自己的内存数据结构,来改变自己对内存区间的使用。还有一个典型的例子是当内核启动参数中有置顶memmap这样的参数项时,内核会修改指定的usable的区间为reserved,这样内核就不能将虚拟地址映射到这些物理地址空间了,换言之就是不能使用这块物理内存了(其实通过ioremap还是可以将其映射到内核的虚拟地址空间的,但是这些行为都是自己控制的而不会受到其他程序的干扰)。这样当我们需要自己管理某段物理内存而不希望内核干预时就很有用处,比如基于物理内存的文件系统,就可以这样实现。内核中还提供了一系列操作e820数据结构的函数,函数声明都在arch/x86/include/asm/e820.h,相应的定义都在arch/x86/kernel/e820.c中。文章开头看到的这段信息,就是由void _init e820_print_map(char *who)来打印的。在这个过程中,e820_saved始终保持原始的状态不变,以便查询BIOS提供的真实映射信息,不过内核目前好像没有使用这个数据结构。我曾经有使用过它,用来检查某个物理地址是否确实是物理内存。inux在被bootloader加载到内存后, cpu最初执行的linux内核代码是/header.S文件中的start_of_setup函数,这个函数在做了一些准备工作后会跳转到boot目下文件main.c的main函数执行,在这个main函数中我们可以第一次看到与内存管理相关的代码,这段代码调用detect_memeory()函数检测系统物理内存在header.S中执行下面汇编代码:1. start_of_setup:2. .3. #JumptoCcode(shouldnotreturn)4. calllmain5. .跳到boot目录下的main.c文件中1. voidmain(void)2. 3. .4. /*Detectmemorylayout*/5. detect_memory();/*内存探测函数*/6. .7. 1. intdetect_memory(void)2. 3. interr=-1;4. 5. if(detect_memory_e820()0)6. err=0;7. 8. if(!detect_memory_e801()9. err=0;10. 11. if(!detect_memory_88()12. err=0;13. 14. returnerr;15. 由上面的代码可知,linux内核会分别尝试调用detect_memory_e820()、detcct_memory_e801()、detect_memory_88()获得系统物理内存布局,这3个函数内部其实都会以内联汇编的形式调用bios中断以取得内存信息,该中断调用形式为int 0x15,同时调用前分别把AX寄存器设置为0xe820h、0xe801h、0x88h,关于0x15号中断有兴趣的可以去查询相关手册。下面分析detect_memory_e820()的代码,其它代码基本一样。1. #defineSMAP0x534d4150/*ASCIISMAP*/2. /*由于历史原因,一些i/o设备也会占据一部分内存3. 物理地址空间,因此系统可以使用的物理内存空4. 间是不连续的,系统内存被分成了很多段,每个段5. 的属性也是不一样的。int0x15查询物理内存时每次6. 返回一个内存段的信息,因此要想返回系统中所有7. 的物理内存,我们必须以迭代的方式去查询。8. detect_memory_e820()函数把int0x15放到一个do-while循环里,9. 每次得到的一个内存段放到structe820entry里,而10. structe820entry的结构正是e820返回结果的结构!而像11. 其它启动时获得的结果一样,最终都会被放到12. boot_params里,e820被放到了boot_params.e820_map。13. */14. staticintdetect_memory_e820(void)15. 16. intcount=0;/*用于记录已检测到的物理内存数目*/17. structbiosregsireg,oreg;18. structe820entry*desc=boot_params.e820_map;19. staticstructe820entrybuf;/*staticsoitiszeroed*/20. 21. initregs(&ireg);/*初始化ireg中的相关寄存器*/22. ireg.ax=0xe820;23. ireg.cx=sizeofbuf;/*e820entry数据结构大小*/24. ireg.edx=SMAP;/*标识*/25. ireg.di=(size_t)&buf;/*int15返回值的存放处*/26. 27. /*28. *Note:atleastoneBIOSisknownwhichassumesthatthe29. *bufferpointedtobyonee820callisthesameoneas30. *thepreviouscall,andonlychangesmodifiedfields.Therefore,31. *weuseatemporarybufferandcopytheresultsentrybyentry.32. *33. *Thisroutinedeliberatelydoesnottrytoaccountfor34. *ACPI3+extendedattributes.Thisisbecausethereare35. *BIOSesinthefieldwhichreportzeroforthevalidbitfor36. *allranges,andwedontcurrentlymakeanyuseofthe37. *otherattributebits.Revisitthisifweseetheextended38. *attributebitsdeployedinameaningfulwayinthefuture.39. */40. 41. do42. /*在执行这条内联汇编语句时输入的参数有:43. eax寄存器=0xe82044. dx寄存器=SMAP45. edi寄存器=desc46. ebx寄存器=next47. ecx寄存器=size48. 49. 返回给c语言代码的参数有:50. id=eax寄存器51. rr=edx寄存器52. ext=ebx寄存器53. size=ecx寄存器54. desc指向的内存地址在执行0x15中断调用时被设置55. */56. intcall(0x15,&ireg,&oreg);57. /*选择下一个*/58. ireg.ebx=oreg.ebx;/*fornextiteration.*/59. 60. /*BIOSeswhichterminatethechainwithCF=1asopposed61. to%ebx=0dontalwaysreporttheSMAPsignatureon62. thefinal,failing,probe.*/63. if(oreg.eflags&X86_EFLAGS_CF)64. break;65. 66. /*SomeBIOSesstopreturningSMAPinthemiddleof67. thesearchloop.WedontknowexactlyhowtheBIOS68. screwedupthemapatthatpoint,wemighthavea69. partialmap,thefullmap,orcompletegarbage,so70. justreturnfailure.*/71. if(oreg.eax!=SMAP)72. count=0;73. break;74. 75. 76. *desc+=buf;/*将buf赋值给desc*/77. count+;/*探测数加一*/78. 79. while(ireg.ebx&countsetup_arch()-setup_memory_map()1. /*调用x86_init.resources.memory_setup()实现对e820内存图的优化,2. 将e820中得值保存在e820_saved中,打印内存图3. */4. void_initsetup_memory_map(void)5. 6. char*who;7. /*调用x86体系下的memory_setup函数*/8. who=x86_init.resources.memory_setup();9. /*保存到e820_saved中*/10. memcpy(&e820_saved,&e820,sizeof(structe820map);11. printk(KERN_INFOBIOS-providedphysicalRAMmap:n);12. /*打印输出*/13. e820_print_map(who);14. 在x86_init.c中定义了x86下的memory_setup函数1. structx86_init_opsx86_init_initdata=2. 3. .resources=4. 5. .memory_setup=default_machine_specific_memory_setup,6. ,7. 8. ;1. char*_initdefault_machine_specific_memory_setup(void)2. 3. char*who=BIOS-e820;4. u32new_nr;5. /*6. *TrytocopytheBIOS-suppliedE820-map.7. *8. *Otherwisefakeamemorymap;onesectionfrom0k-640k,9. *thenextsectionfrom1mb-appropriate_mem_k10. */11. new_nr=boot_params.e820_entries;12. /*将重叠的去除*/13. sanitize_e820_map(boot_params.e820_map,14. ARRAY_SIZE(boot_params.e820_map),15. &new_nr);16. /*去掉重叠的部分后得到的内存个数*/17. boot_params.e820_entries=new_nr;18. /*将其赋值到全局变量e820中,小于0时,为出错处理*/1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论