dex*_*ous 6 c linux linux-kernel
虚拟内存对我来说是一个非常复杂的话题.我想了解它.以下是我对32位系统的理解.示例RAM仅为2GB.我试过阅读很多链接,目前我并不自信.我希望你们有人帮助我清理我的概念.请承认我的观点,也请回答你的错误.在我的观点中,我也有一个困惑的部分.所以,这里开始总结.
每个进程都认为它只是在运行.它可以访问4GB的内存 - 虚拟地址空间.
当进程访问虚拟地址时,它将通过MMU转换为物理地址.该MMU是CPU的一部分 - 硬件.
当MMU无法将地址转换为物理地址时,会引发页面错误.
在页面错误时,会通知内核.内核检查VM区域结构.如果它能找到它 - 可能在磁盘上.它会做一些页面输入/页面输出.并在RAM上获取此内存.
现在MMU将再次尝试并且这次将成功.
如果内核找不到地址,它将发出一个信号.例如,无效访问将引发SIGSEGV.
困惑点.
Page表是否在内核中维护?这个VM区域结构有一个页表?
MMU如何在物理RAM中找不到该地址.让我们说它转换为RAM中的一些错误地址.代码仍将执行,但它将是一个糟糕的地址.MMU如何确保正在读取正确的数据?它是否每次都参考内核VM区域?
Mapping表 - 虚拟到物理是否在MMU内.我读过它是由一个单独的过程维护的.如果它在一个过程中,为什么我看不到它.或者,如果它是MMU,MMU如何生成地址 - 是Segment + 12位移位 - >页面帧编号,然后添加偏移(位-1到10) - >给出物理地址.对于32位架构而言,这是否意味着我的想法.我可以从虚拟地址确定物理地址.
cat/proc/pid_value/maps.这向我展示了vmarea的当前映射.基本上,它读取Vmarea结构并打印它.这意味着这很重要.我无法完整地了解这一部分.执行程序时,会生成vmarea结构.当MMU无法转换地址(即页面错误)时,VMAREA是否仅进入画面?当我打印vmarea时,它显示地址范围,权限并映射到文件描述符和偏移量.我确信这个文件描述符是硬盘中的文件描述符,偏移量是该文件的.
高内存概念是内核无法直接访问大于1 GB(大约)的内存区域.因此,它需要一个页表来间接映射它.因此,它会临时加载一些页表来映射地址.HIGH MEM每次都会进入画面吗?因为Userspace可以通过MMU直接转换地址.在什么情况下,内核真的想要访问高MEM.我相信内核驱动程序主要使用kmalloc.这是直接内存+偏移地址.在这种情况下,实际上不需要映射.因此,问题是内核需要访问High Mem的场景.
处理器是否专门配备了MMU支持.那些没有MMU支持的人无法运行LInux?
- Page表是否在内核中维护?这个VM区域结构有一个页表?
是.不完全是:每个进程都有一个mm_struct,它包含一个列表vm_area_struct(表示抽象,独立于处理器的内存区域,也就是映射),以及一个名为的字段pgd,它是指向特定于处理器的页表的指针(包含每页的当前状态:有效,可读,可写,脏,......).
页表不需要完整,OS可以从VMA生成它的每个部分.
- MMU如何在物理RAM中找不到该地址.让我们说它转换为RAM中的一些错误地址.代码仍将执行,但它将是一个糟糕的地址.MMU如何确保正在读取正确的数据?它是否每次都参考内核VM区域?
转换失败,例如因为页面被标记为无效,或者尝试对只读页面进行写访问.
- Mapping表 - 虚拟到物理是否在MMU内.我读过它是由一个单独的过程维护的.如果它在一个过程中,为什么我看不到它.或者,如果它是MMU,MMU如何生成地址 - 是Segment + 12位移位 - >页面帧编号,然后添加偏移(位-1到10) - >给出物理地址.对于32位架构而言,这是否意味着我的想法.我可以从虚拟地址确定物理地址.
常用的MMU有两种.其中一个只有一个TLB(Translation Lookaside Buffer),它是页表的缓存.当TLB没有针对尝试访问的转换时,生成TLB未命中,OS执行页表行走,并将转换放入TLB中.
另一种MMU使页面表在硬件中行走.
在任何情况下,操作系统都会为每个进程维护一个页表,这会将虚拟页码映射到物理帧号.此映射可以随时更改,当页面被页面调入时,它映射到的物理帧取决于可用内存的可用性.
- cat/proc/pid_value/maps.这向我展示了vmarea的当前映射.基本上,它读取Vmarea结构并打印它.这意味着这很重要.我无法完整地了解这一部分.执行程序时,会生成vmarea结构.当MMU无法转换地址(即页面错误)时,VMAREA是否仅进入画面?当我打印vmarea时,它显示地址范围,权限并映射到文件描述符和偏移量.我确信这个文件描述符是硬盘中的文件描述符,偏移量是该文件的.
至于第一个近似值,是的.除此之外,内核可能决定调整进程内存的原因有很多,例如:如果存在内存压力,它可能会决定从某个随机进程中分页出一些很少使用的页面.用户空间内也能操控通过映射mmap(),execve()以及其他系统调用.
- 高内存概念是内核无法直接访问大于1 GB(大约)的内存区域.因此,它需要一个页表来间接映射它.因此,它会临时加载一些页表来映射地址.HIGH MEM每次都会进入画面吗?因为Userspace可以通过MMU直接转换地址.在什么情况下,内核真的想要访问高MEM.我相信内核驱动程序主要使用kmalloc.这是直接内存+偏移地址.在这种情况下,实际上不需要映射.因此,问题是内核需要访问High Mem的场景.
与其他问题完全无关.总之,高内存是一种能够在有限的地址空间计算机中访问大量内存的黑客.
基本上,内核为它保留了有限的地址空间(在x86上,典型的用户/内核拆分是3Gb/1Gb [进程可以在用户空间或内核空间中运行.当调用系统调用时,进程在内核空间中运行.避免必须在每个上下文切换上切换页表,在x86上通常地址空间在用户空间和内核空间之间分开]).因此内核可以直接访问高达~1Gb的内存.为了访问更多的物理内存,需要一些间接性,这就是高内存的全部意义.
- 处理器是否专门配备了MMU支持.那些没有MMU支持的人无法运行Linux?
笔记本电脑/台式机处理器配有MMU.x86支持自386以来的分页.
Linux,特别是名为μCLinux的变体,支持没有MMU(!MMU)的处理器.许多嵌入式系统(ADSL路由器......)使用没有MMU的处理器.有一些重要的限制,其中包括:
fork().mmap()首次加载程序时,内核会为该进程设置内核VM-Area吗?该内核VM区域实际上保存在存储器/ HDD中的程序部分的位置.然后更新CR3寄存器,页面演练或TLB的整个故事如图所示?那么,每当有页面错误时 - 内核会通过查看内核虚拟内存区来更新页面表吗?但他们说内核VM区域不断更新.这是怎么可能的,因为cat/proc/pid_value/map将不断更新.从开始到结束,地图不会是恒定的.那么,真正的信息是在内核VM区域结构中可用的吗?这是程序部分所在的实际信息,它可能是HDD或物理内存 - RAM?那么,这是在流程加载过程中填充的第一份工作吗?内核页面输出页面出错了,并且会更新内核VM区域吗?那么,它还应该知道硬盘上的整个程序位置是否正确?请在这里纠正我.这是我对上一条评论的第一个问题的延续.
当内核加载一个程序时,它会根据可执行文件中的段(你可以看到的ELF文件)设置几个VMA(映射),这些段readelf --segments将是文本/代码段,数据段等...该程序的生命周期期间,可能由动态/运行时链接来创建附加映射,由内存分配器(malloc(),其也可以通过扩展数据段brk()),或者直接通过经由程序mmap(),shm_open()等.
VMA包含生成页表的必要信息,例如,它们判断该内存是由文件还是由swap(匿名内存)支持.所以,是的,内核将通过查看VMA来更新页面表.内核将在内存中进行寻呼以响应页面错误,并将响应内存压力分页内存.
使用x86无PAE作为示例:
在没有PAE的x86上,线性地址可以分成3个部分:前10位指向页目录中的条目,中间10位指向上述页目录条目指向的页表中的条目.页表条目可以包含有效的物理帧号:物理地址的前22位.虚拟地址的底部12位是页面中未转换为物理地址的偏移量.
每次内核调度不同的进程时,CR3寄存器都会被写入指向当前进程的页面目录的指针.然后,每次进行内存访问时,MMU都会尝试查找TLB中缓存的转换,如果找不到,则会查找从CR3开始执行页表行走的转换.如果仍然没有找到,则引发GPF故障,CPU切换到Ring 0(内核模式),内核尝试在VMA中找到一个.
另外,我相信这个读取来自CR,页面目录 - >页面表 - >页面帧号 - 内存地址这一切都是由MMU完成的.我对么?
在x86上,是的,MMU执行页表行走.在其他系统(例如:MIPS)上,MMU仅仅是TLB,而在TLB未命中异常时,内核通过软件执行页表行走.