漫画解说 “内存映射”

存储 存储软件
虚拟内存地址就好比每个班的学号,而物理内存地址就好比真实的学生。因为每个学号都对应不同的学生,所以虚拟内存地址也要映射到物理内存地址。

[[396240]]

本文转载自微信公众号「Linux内核那些事」,作者songsong001。转载本文请联系Linux内核那些事公众号。

 

虚拟内存空间与物理内存空间

虚拟内存地址就好比每个班的学号,而物理内存地址就好比真实的学生。因为每个学号都对应不同的学生,所以虚拟内存地址也要映射到物理内存地址。

虚拟内存与物理内存的映射关系是通过 页表 来关联的,如下图:

但 页表 并不是按字节来进行映射的,而是按照 内存页 为单位进行映射,一般一个 内存页 的大小为 4KB(为什么要加一般呢,这是因为除了4KB,还有其他大小的内存页,如2MB,4MB,1GB等),页表 的每一个 页表项 都保存着物理内存页的地址。

所以,4GB 的虚拟内存空间需要 1MB 大小的页表来关联(因为 4GB / 4KB = 1MB)。也就是说,0 ~ 4095 的虚拟内存地址都是使用 页表 的第一个 页表项 来映射的,而 4096 ~ 8191 的虚拟内存地址使用 页表 的第二个 页表项 来映射的,以此类推...

那么,通过什么样的算法能把 0 ~ 4095 的虚拟内存地址转换为页表的第一个页表项呢?其实很简单,只需要把虚拟内存地址的高端 20 位作为页表的索引,而把低端 12 位作为内存页中的偏移量即可,如下图:

在上图中,还看到了一个 cr3 的东西,这是 CPU 中的一个寄存器,用于保存 页表 的物理内存地址,通过这个寄存器就能找到进程的 页表 了。

现在对内存映射的原理有了比较清晰的了解了,但现在有个问题,每个进程都要 1MB 大小的页表,那不是很浪费内存吗?的确是,因为进程很多虚拟内存地址并不会用到,为了节省页表使用的内存,x86 CPU 把页表分为 2 级,如下图:

如上图所示,把原来的 页表 划分为 页目录 和 页表,它们的大小均为 4KB。而虚拟内存地址的高 10 位作为页目录的索引,而中间 10 位作为页表的索引,低 12 位还是作为物理内存页的偏移量。

把原来的 页表 划分为两级后,进程有些不使用的虚拟内存地址就不需要进行映射,从而节省了内存的使用。

 

责任编辑:武晓燕 来源: Linux内核那些事
相关推荐

2013-10-12 13:01:51

Linux运维内存管理

2009-07-24 10:00:38

.NET 4.0内存映

2011-04-25 17:15:39

MongodbMMAP

2012-06-20 14:16:36

Java内存映射

2023-03-01 10:37:51

2020-09-17 08:28:08

内存映射反向

2010-05-10 14:15:54

DNS负载均衡

2010-08-26 13:38:45

DHCP冗余

2021-12-03 16:20:26

鸿蒙HarmonyOS应用

2009-08-13 14:21:04

.NET内存映射文件

2021-11-11 05:00:02

JavaMmap内存

2009-01-09 22:29:38

服务器虚拟化磁盘阵列

2010-07-06 10:00:08

UML部署图

2010-09-02 14:42:04

DHCP Relay

2018-10-10 14:14:51

Linux内存映射

2023-06-28 08:27:49

CLR断点C#

2021-04-29 18:11:03

虚拟IPKeeplived

2010-10-15 10:33:37

2010-02-04 15:01:07

Android架构

2009-09-23 15:37:52

Hibernate 原
点赞
收藏

51CTO技术栈公众号