我们必须首先了解需要内存管理的原因。
早期的程序直接在物理地址上运行,这意味着该程序所需的空间不会超过计算机的物理内存。
不会有问题,但是在实际情况下不会有问题。
它是多任务,多进程的,为每个进程保留的这种物理地址是不可靠的。
以栗子为例:如果有3个程序a,b,c,并且需要10M,b需要100M,c需要20M,则总内存为120M,根据前面的分配方法,将前10M分配给a,并且b给10M-110M,系统还剩10M,而c需要20M。
显然,剩余的内存不足以容纳c。
该怎么办? 1.效率问题。
您可能会想到在c程序运行时将b程序数据写入磁盘,然后在b运行时从磁盘写回数据。
更不用说b无法满足。
c程序并行运行。
需求,甚至是由频繁的io操作导致的耗时的问题也是无法接受的。
2.进程地址隔离问题除了效率问题之外,如果需要其他进程访问该进程的保留空间,则该进程的保留空间将崩溃。
例如,进程a访问的空间是前10M,但是程序中访问10-110M的一段代码可能会导致b程序崩溃,因此需要将进程的地址空间彼此隔离。
3.重定位问题在实际情况下,单个任务不可能在划分良好的内存中运行。
当多个任务并行运行时,可以动态申请释放内存,从而可以在其他进程中申请地址。
这时,您需要重新定位到新地址。
内存管理不过是试图解决以上三个问题而已。
如何提高内存使用效率?如何隔离进程的地址空间?程序运行时如何解决重定位问题?如何将内存管理从虚拟地址映射到物理地址:内存管理从虚拟地址映射到物理地址的过程是解决上述三个问题的过程。
内存管理使用分段机制和分页机制分别解决上述三个问题。
大致过程如下:分段机制:只要将程序划分为多个段,将整个段转换为任意位置后,该段内的地址就相对于该段的基址是恒定的,无论段的基地址是什么,只要给出段中的偏移地址,CPU就可以访问正确的指令。
因此,在加载用户程序时,只要将整个节的内容复制到新位置,然后将节基地址寄存器中的地址更改为该地址,程序就可以准确地运行,因为该程序使用段中的偏移地址,相对新的段基地址,偏移地址的内容仍然相同。
可以看出,分段机制解决了进程间的隔离和重定位问题。
此操作在硬件中完成,但是某些硬件没有分段机制。
作为跨平台的linux,它使用一种更通用的分页机制来解决从线性地址到虚拟地址到物理地址的转换。
分页机制:您可以参考“ CPU如何访问内存?”。
了解第一页表的概念。
为了与32位和64位兼容,Linux通常使用四级页面表,页面全局目录,页面上层目录和页面中间目录。
页表:我不会详细解释Linux如何使用四级页表将线性地址(虚拟地址)转换为物理地址。
切换进程时,它将根据task_struct在mm_struct中找到pgd字段,获取新进程的页面全局目录,然后将其填充到CR3寄存器中以完成页面切换。
让我们看一下mmu分页寻址的过程:可以看出,对应于虚拟地址ffff99b488d48000的物理地址是80000000c8d48000。
这个过程也是mmu的过程。