对我来说,虚拟内存是一个非常复杂的话题。我想了解它。这是我对32位系统的理解。示例RAM仅为2GB。我尝试阅读许多链接,但目前我还没有信心。我希望你们能帮助我阐明我的概念。请承认我的观点,也请回答您认为错误的地方。我的观点中也有一个困惑的部分。因此,这里开始摘要。
该MMU是CPU的一部分-硬件。
混淆点。
或者,如果是MMU,则MMU如何生成地址-是段+ 12位移位->页面帧号,然后加上偏移量(-1至10位)->给出一个物理地址。
在我心中,对于32位体系结构,这是否意味着这种计算。我可以从虚拟地址中确定物理地址。
最佳答案
是的。不完全正确:每个进程都有一个mm_struct,其中包含vm_area_struct
的列表(代表抽象的,与处理器无关的内存区域,又名映射),以及一个称为pgd
的字段,该字段是指向特定于处理器的页表的指针(其中包含每个页面的当前状态:有效,可读,可写,脏,...)。
页表不需要完整,操作系统可以从VMA生成页表的每个部分。
翻译失败,例如因为该页面被标记为无效,或者试图对只读页面进行写访问。
常用的MMU有两种。其中之一只有一个TLB(转换后备缓冲区),它是页表的缓存。当TLB没有尝试访问的转换时,将生成TLB未命中,OS进行页表遍历,并将转换放入TLB中。
另一种MMU在硬件中执行页表。
在任何情况下,操作系统都会为每个进程维护一个页表,这会将虚拟页号映射到物理帧号。当页面被调入页面时,此映射可以随时更改,其映射到的物理帧取决于可用内存的可用性。
第一次近似,是的。除此之外,内核还有很多原因可以决定摆弄进程的内存,例如:如果存在内存压力,它可能决定从某个随机进程中调出一些很少使用的页面。用户空间还可以通过mmap()
,execve()
和其他系统调用来操纵映射。
完全与其他问题无关。总之,高内存是一种能够在有限的地址空间计算机中访问大量内存的技术。
基本上,内核保留有一个有限的地址空间(在x86上,典型的用户/内核拆分为3Gb/1Gb [进程可以在用户空间或内核空间中运行。当调用syscall时,进程在内核空间中运行。避免必须在每个上下文切换上切换页面表,通常在x86上,地址空间在用户空间和内核空间之间进行划分]。因此内核可以直接访问约1Gb的内存。要访问更多的物理内存,需要使用一些间接方法,这就是高级内存的全部含义。
笔记本电脑/台式机处理器随附MMU。从386开始,x86支持分页。
Linux,特别是称为µCLinux的变体,支持不带MMU(!MMU)的处理器。许多嵌入式系统(ADSL路由器等)使用不带MMU的处理器。有一些重要的限制,其中包括:
fork()
。 mmap()
当内核加载程序时,它将根据可执行文件中的段(在ELF文件中您可以通过
readelf --segments
看到)设置多个VMA(映射),这些段将是文本/代码段,数据段等。在程序的生命周期内,动态/运行时链接程序,内存分配器(malloc()
,也可以通过brk()
扩展数据段)或直接由程序通过mmap()
,shm_open()
等创建其他映射。 。VMA包含生成页表所需的信息,例如他们告诉该内存是由文件支持还是由交换支持(匿名内存)。因此,是的,内核将通过查看VMA来更新页表。内核将响应页面错误而在内存中进行页面调度,并响应于存储器压力而将内存进行页面调度。
以x86 no PAE为例:
在没有PAE的x86上,线性地址可以分为3部分:前10位指向页面目录中的条目,中间10位指向页面表中由上述页面目录条目指向的条目。页表条目可能包含有效的物理帧号:物理地址的前22位。虚拟地址的低12位是页面的偏移量,该偏移量未转换为物理地址。
每次内核调度一个不同的进程时,将使用指向当前进程的页面目录的指针写入CR3寄存器。然后,每次进行内存访问时,MMU都会尝试查找缓存在TLB中的转换,如果找不到,则从CR3开始查找进行页表遍历的转换。如果仍然找不到一个,则会引发GPF故障,CPU切换到Ring 0(内核模式),内核会尝试在VMA中找到一个。
在x86上,是的,MMU执行页表遍历。在其他系统(例如:MIPS)上,MMU仅比TLB多一点,而在TLB未命中的情况下,内核会通过软件进行页表遍历。