我正在学习linux内核内部,在阅读“理解Linux内核”时,有很多与内存相关的问题让我感到震惊。其中之一是,如果我的系统上安装了仅512 MB的物理内存,Linux内核如何处理内存映射。
正如我所读到的,内核将 0(或16)MB-896MB 物理RAM映射到0xC0000000线性地址,并可直接对其进行寻址。所以,在上面描述的情况下,我只有512 MB:
内核如何从512 MB映射896 MB?在所描述的方案中,内核进行设置,以便每个进程的页表将虚拟地址从0xC0000000映射到0xFFFFFFFF(1GB),直接映射到0x00000000到0x3FFFFFFF(1GB)的物理地址。但是当我只有512 MB物理RAM时,如何将虚拟地址从0xC0000000-0xFFFFFFFF映射到物理0x00000000-0x3FFFFFFF?点是我的物理范围只有0x00000000-0x20000000。
在这种情况下用户模式进程怎么样?
每篇文章都只解释了这种情况,当你安装了4 GB内存并且内核将1 GB映射到内核空间时,用户进程使用剩余的RAM。
我希望能帮助你提高理解力。
谢谢..!
答案 0 :(得分:44)
并非所有虚拟(线性)地址都必须映射到任何地址。如果代码访问未映射的页面,则页面错误会增加。
物理页面可以同时映射到多个虚拟地址。
在4 GB虚拟内存中有2个部分:0x0 ... 0xbfffffff - 是进程虚拟内存和0xc0000000 .. 0xffffffff是内核虚拟内存。
它最多映射到896 MB。因此,如果您只有512,则只会映射512 MB。
如果您的物理内存在0x00000000到0x20000000之间,它将被映射为直接内核访问虚拟地址0xC0000000到0xE0000000(线性映射)。
用户进程的物理内存将被映射(不是顺序的,而是随机的页面到页面的映射)到虚拟地址0x0 .... 0xc0000000。此映射将是0..896MB页面的第二个映射。这些页面将从免费页面列表中获取。
任何地方。
没有。每篇文章都解释了如何映射4 Gb的虚拟地址空间。虚拟内存的大小总是4 GB(对于没有内存扩展的32位机器,如x86的PAE / PSE / etc)
如Robert Love所着的8.1.3. Memory Zones
(我使用的是第三版)Linux Kernel Development
所述,有几个物理记忆区域:
因此,如果你有512 MB,你的ZONE_HIGHMEM将为空,ZONE_NORMAL将有496 MB的物理内存映射。
另外,请查看本书的2.5.5.2. Final kernel Page Table when RAM size is less than 896 MB
部分。当你的内存少于896 MB时就是这种情况。
此外,对于ARM,还有一些虚拟内存布局的描述:http://www.mjmwired.net/kernel/Documentation/arm/memory.txt
第63行PAGE_OFFSET high_memory-1
是内存的直接映射部分
答案 1 :(得分:17)
硬件提供Memory Management Unit。它是一个能够拦截和改变任何存储器访问的电路。每当处理器访问RAM时,例如要读取下一条要执行的指令,或者作为由指令触发的数据访问,它会在某个地址处执行此操作,粗略地说,这是32位值。 32位字可以有超过4亿个不同的值,因此存在4 GB的地址空间:这是可以具有唯一地址的字节数。 / p>
因此处理器将请求发送到其内存子系统,因为"获取地址 x 处的字节并将其返回给我"。该请求通过MMU决定如何处理请求。 MMU虚拟地将4 GB空间拆分为页面;页面大小取决于您使用的硬件,但典型大小为4和8 kB。 MMU使用表来告诉它如何处理每个页面的访问:访问被授予重写的地址(页面条目说:"是的,包含地址 x 的页面存在,它位于地址 y ")的物理RAM中或被拒绝,此时调用内核以进一步处理事情。内核可能决定终止违规进程,或者做一些工作并改变MMU表,以便可以再次尝试访问,这次成功。
这是虚拟内存的基础:从这个角度来看,该进程有一些RAM,但是内核已经将它移动到了硬盘上,在#34>交换空间&#34 ;。相应的表格标记为"缺席"在MMU表中。当进程访问其数据时,MMU调用内核,该内核从交换中获取数据,将其放回物理RAM中的某个空闲空间,并将MMU表更改为指向该空间。然后内核跳回到进程代码,就在触发整个事件的指令处。除了内存访问花了很长时间之外,进程代码没有看到整个业务。
MMU还处理访问权限,这会阻止进程读取或写入属于其他进程或内核的数据。每个进程都有自己的一组MMU表,内核管理这些表。因此,每个进程都有自己的地址空间,就像在具有4 GB RAM的计算机上一样 - 除了进程最好不能访问它没有从内核中正确分配的内存,因为相应的页面被标记缺席或禁止。
当通过某个进程的系统调用调用内核时,内核代码必须在进程的地址空间内运行;因此内核代码必须位于每个进程的地址空间中(但受保护:MMU表阻止从非特权用户代码访问内核内存)。由于代码可以包含硬编码地址,因此内核最好位于所有进程的相同地址;通常,在Linux中,该地址是0xC0000000。每个进程的MMU表将地址空间的一部分映射到任何物理 RAM,阻止内核在引导时实际加载。请注意,内核内存永远不会被换出(如果可以从交换空间读回数据的代码本身被换掉,那么事情会变得非常快)。
在PC上,事情可能会有点复杂,因为有32位和64位模式,段寄存器和PAE(充当一种具有大页面的二级MMU)。基本概念保持不变:每个进程都有自己的虚拟4 GB地址空间视图,内核使用MMU将每个虚拟页面映射到RAM中的适当物理位置,或者根本不存在。
答案 2 :(得分:4)
osgx有一个很好的答案,但我看到有人仍然不理解的评论。
每篇文章仅解释了您安装4 GB的情况 内存和内核将1 GB映射到内核空间和用户 进程使用剩余的RAM量。
这里有很多困惑。有虚拟内存,并且有物理内存。每个32位CPU都有4GB的虚拟内存。 Linux内核的传统拆分是用于用户内存和内核内存的3G / 1G,但更新的选项允许不同的分区。
为什么要区分内核和用户空间? - 我自己的问题
当任务交换时,必须更新MMU。对于所有进程,内核MMU空间应保持相同。内核必须随时处理中断和错误请求。
虚拟到物理映射如何工作? - 我自己的问题。
虚拟内存的排列很多。
从上面的列表中,很容易看出为什么您可能拥有比物理内存更多的虚拟地址空间。实际上,错误处理程序通常会检查进程内存信息,以查看页面是映射(我的意思是分配给进程),但不是在内存中< / em>的。在这种情况下,故障处理程序将调用I / O子系统来读取页面。读取页面并更新MMU表以将虚拟地址指向新的物理地址后,导致故障的过程将恢复。
如果您了解上述内容,就会明白为什么您希望拥有比物理内存更大的虚拟映射。这是支持内存交换的方式。
还有其他用途。例如,两个进程可以使用相同的代码库。由于链接,它们可能位于进程空间中的不同虚拟地址。在这种情况下,您可以将不同的虚拟地址映射到相同的物理页面,以节省物理内存。这对于新的分配来说非常普遍;他们都指向一个实际的零页面#39;当您触摸/写入内存时,将复制零页面并分配新的物理页面(COW或写入时复制)。
将虚拟页面替换为缓存,将另一个虚拟页面替换为非缓存有时也很有用。可以检查这两个页面以查看缓存的数据和不缓存的数据。
主要是虚拟和物理不一样!容易陈述,但在查看Linux VMM代码时经常会感到困惑。
答案 3 :(得分:3)
-
嗨,实际上,我不在x86硬件平台上工作,因此我的帖子中可能存在一些技术错误。
据我所知,当你有比这个数字更多的RAM时,会特别列出0(或16)MB - 896MB之间的范围,比如说,你的主板上有1GB物理RAM,称为“低内存”。如果您的主板上有超过896MB的物理RAM,则物理RAM的其余部分称为highmem。
说到你的问题,你的主板上有512MiBytes物理内存,所以实际上没有896,没有highmem。
总RAM内核可以看到并且也可以映射为512MB。
'因为物理内存和内核虚拟地址之间存在一对一的映射,因此内核有512MiBytes的虚拟地址空间。我真的不确定先前的句子是否正确,但这是我的想法。
我的意思是如果有512MBytes,那么内核可以管理的物理RAM量也是512MiBytes,而且,内核无法创建超过512MBytes的大地址空间。
参考用户空间,有一个不同点,用户应用程序的页面可以换成硬盘,但内核的页面不能。
因此,对于用户空间,借助页表和其他相关模块,似乎仍有4GB的地址空间。 当然,这是虚拟地址空间,而不是物理RAM空间。
这是我理解的。
感谢。
答案 4 :(得分:0)
如果物理内存小于896 MB,则linux内核会直接映射到该物理地址。
有关详细信息,请参阅此.. http://learnlinuxconcepts.blogspot.in/2014/02/linux-addressing.html