Linux系统下及内存映射原理.docVIP

  1. 1、本文档共5页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
Linux系统下及内存映射原理

内存映射 ? ? 对于提供了MMU(存储管理器,辅助操作系统进行内存管理,提供虚实地址转换等硬件支持)的处理器而言,Linux提供了复杂的存储管理系统,使得进程所能访问的内存达到4GB。   进程的4GB内存空间被人为的分为两个部分--用户空间和内核空间。用户空间地址分布从0到3GB(PAGE_OFFSET,在0x86中他等于0xC0000000),3GB到4GB为内核空间,如下图:   内核空间中,从3G到vmalloc_start这段地址是物理内存映射区域(该区域中包含了内核映像、物理页框表mem_map等等),比如我们使 用的VMware虚拟系统内存是160M,那么3G~3G+160M这片内存就应该映射物理内存。在物理内存映射区之后,就是vmalloc区域。对于 160M的系统而言,vmalloc_start位置应在3G+160M附近(在物理内存映射区和vmalloc_start期间还存在一个8M的gap 来防止跃界),vmalloc_end的位置接近4G(最后位置系统会保留一片128k大小的区域用于专用页面映射),如下图:   kmalloc和get_free_page申请的内存位于物理内存映射区域,而且在物理上也是连续的,他们和真实的物理地址只有一个固定的偏移,因此存在较简单的转换关系,virt_to_phys()能够实现内核虚拟地址转化为物理地址: #define __pa(x) ((unsigned long)(x)_OFFSET) extern inline unsigned long virt_to_phys(volatile void * address) {  return __pa(address); }   上面转换过程是将虚拟地址减去3G(PAGE_OFFSET=0XC000000)。   和之对应的函数为phys_to_virt(),将内核物理地址转化为虚拟地址: #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) extern inline void * phys_to_virt(unsigned long address) {  return __va(address); }   virt_to_phys()和phys_to_virt()都定义在include\asm-i386\io.h中。   而vmalloc申请的内存则位于vmalloc_start~vmalloc_end之间,和物理地址没有简单的转换关系,虽然在逻辑上他们也是连续的,但是在物理上他们不需要连续。   我们用下面的程式来演示kmalloc、get_free_page和vmalloc的区分: #include #include #include MODULE_LICENSE(GPL); unsigned char *pagemem; unsigned char *kmallocmem; unsigned char *vmallocmem; int __init mem_module_init(void) {  //最好每次内存申请都检查申请是否成功  //下面这段仅仅作为演示的代码没有检查  pagemem = (unsigned char*)get_free_page(0);  printk(pagemem addr=%x, pagemem);  kmallocmem = (unsigned char*)kmalloc(100, 0);  printk(kmallocmem addr=%x, kmallocmem);  vmallocmem = (unsigned char*)vmalloc(1000000);  printk(vmallocmem addr=%x, vmallocmem);  return 0; } void __exit mem_module_exit(void) {  free_page(pagemem);  kfree(kmallocmem);  vfree(vmallocmem); } module_init(mem_module_init); module_exit(mem_module_exit);   我们的系统上有160MB的内存空间,运行一次上述程式,发现pagemem的地址在0xc7997000(约3G+121M)、 kmallocmem 地址在0xc9bc1380(约3G+155M)、vmallocmem的地址在0xcabeb000(约3G+171M)处,符合前文所述的内存布局。   接下来,我们讨论Linux设备驱动究竟怎样访问外设的I/O端口(寄存器)。   几乎每一种外设都是通过读写设备上的寄存器来进行的

文档评论(0)

liwenhua00 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档