前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[linux][memory]内存映射技术分析

[linux][memory]内存映射技术分析

作者头像
皮振伟
发布2018-04-09 11:01:02
2.3K0
发布2018-04-09 11:01:02
举报
文章被收录于专栏:皮振伟的专栏

前言: KVM的设备虚拟化,除了前文《PIO技术分析》,还有另外一个核心概念---MMIO。原计划这里分析一下KVM的MMIO虚拟化。考虑到MMIO比PIO复杂很多,涉及更多的概念,作者打算先分析几篇基本的Linux的内存管理概念,再来分析MMIO。 作者大概想了一下,主要由这几篇构成: 1,虚拟内存管理和内存映射。 2,物理内存管理。 3,内存回收。 分析: 1,虚拟内存概念 x86的CPU有两种运行模式---real mode和protected mode。在real mode下,CPU访问的是物理地址,也就是说,比如说CPU访问的地址是0x1234,那么访问的物理内存的地址就是0x1234。在protected mode下,访问的虚拟内存,如果访问0x1234这个虚拟地址,那么可能物理上是0xabcde234;从虚拟地址到物理的转换,是通过MMU完成的。 使用虚拟内存后的好处是什么呢?作者认为做大的好处是可以做到进程隔离,也就是说,每个进程都可以有自己的地址空间,互相之间不干扰。当然,还有很多高级的内存特性,例如COW(copy on write)等。 2,进程的地址空间 查看一个进程的地址空间:cat /proc/PID/maps

如图,一个进程的地址空间有多个虚拟内存区域(VMA,virtual memory area)构成,每段VMA包括:起始地址和结束地址(例如例子中的十六进制00400000-004f4000);访问权限(rwx代表读、写、运行);最后那段例如/bin/bash,代表文件映射,如果是空的,则是匿名映射。 如果访问的内存,不在区间内(比如说访问NULL,0明显不在区间内),或者权限不对(比如写了没有w权限的地址),都会发生segmentation fault。 3,VMA管理 linux-4.0.4/include/linux/mm_types.h中定义了VMA的内核态数据结构:

这个数据非常非常非常重要!!!理解Linux内核的虚拟内存管理的关键。从注释中也可以看到,vm_start就是当前这个VMA的起始虚拟地址,vm_end是结束地址后的一个byte的地址,vm_page_prot是访问权限等。 vm_next和vm_prev可以把当前进程的所有的VMA链接起来,vm_rb是给红黑树使用的。同时用链表和红黑树把进程的VMA组织起来,好处在于:可以使用链表进行遍历,可以使用红黑树进行快速查找地址是不是在VMA中。

linux-4.0.4/mm/mmap.c中实现了brk、mmap、munmap、mremap系统调用。结合上面的数据结构,仔细阅读这几个系统调用的实现,大致可以看懂vma的申请、释放、合并、拆分管理。 4,物理内存 在shell中敲dmesg:

可以看到类似的log,BIOS通过e820数据结构告诉Linux物理内存的layout情况。可能你会觉得,为什么插入的一条8G的内存条,会变成这个样子呢?据一位懂BIOS的人和我说,BIOS中也可以配置一次,再做一次映射~ 5,内存映射 看上面例子中的虚拟地址空间,和物理地址范围,二者其实不是对应的。 如上文,CPU在进入了protected mode之后,就会使用虚拟内存了。linux会组织起来一个数据叫做page table(传说中的页表),把虚拟内存和物理内存之间的映射关系保存到page table中,再把page table的地址告诉MMU,MMU就可以在CPU访问虚拟地址的时候,自动转换到物理地址了。

大概转换关系如上图(选自https://en.wikipedia.org/wiki/Page_table)。 6,/dev/mem busybox提供了一个命令---devmem。可以通过devmem直接查看或者修改物理内存。作者在这里在唠叨一下,busybox的代码比较短小精悍,非常不错,值得阅读! devmem的主要是通过/dev/mem做映射实现的。/dev/mem的代码实现在linux-4.0.4/drivers/char/mem.c:

remap_pfn_range是关键函数:函数中实现了pud、pmd、pte的运算,并把物理内存的地址填入pte中。 仔细,完整的阅读remap_pfn_range函数,大概就了解内存映射了。 后记: 因为这里主要是给后面的MMIO做铺垫,所以在这里就没有详细介绍Linux的内存映射技术。当然,还是列举了几处关键代码,如果按照上述的过程,仔细阅读代码,并尝试printk一下,用用提到的命令,作者相信应该比较容易理解。 Good Luck~

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-02-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AlwaysGeek 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档