【一步一图带你深入理解 Linux 虚拟内存管理】高 128 T 表示内核态虚拟内存空间 , 虚拟内存地址范围为:0xFFFF 8000 0000 0000- 0xFFFF FFFF FFFF FFFF。
这样一来就在用户态虚拟内存空间与内核态虚拟内存空间之间形成了一段 0x0000 7FFF FFFF F000-0xFFFF 8000 0000 0000的地址空洞 , 我们把这个空洞叫做 canonical address 空洞 。

文章插图
那么这个 canonical address 空洞是如何形成的呢?
我们都知道在 64 位机器上的指针寻址范围为 2^64 , 但是在实际使用中我们只使用了其中的低 48 位来表示虚拟内存地址 , 那么这多出的高 16 位就形成了这个地址空洞 。
大家注意到在低 128T 的用户态地址空间:0x0000 0000 0000 0000 - 0x0000 7FFF FFFF F000 范围中 , 所以虚拟内存地址的高 16 位全部为 0。
如果一个虚拟内存地址的高 16 位全部为 0 , 那么我们就可以直接判断出这是一个用户空间的虚拟内存地址 。
同样的道理 , 在高 128T 的内核态虚拟内存空间:0xFFFF 8000 0000 0000 - 0xFFFF FFFF FFFF FFFF 范围中 , 所以虚拟内存地址的高 16 位全部为 1。
也就是说内核态的虚拟内存地址的高 16 位全部为 1 , 如果一个试图访问内核的虚拟地址的高 16 位不全为 1 , 则可以快速判断这个访问是非法的 。
这个高 16 位的空闲地址被称为 canonical。如果虚拟内存地址中的高 16 位全部为 0 (表示用户空间虚拟内存地址)或者全部为 1 (表示内核空间虚拟内存地址) , 这种地址的形式我们叫做 canonical form , 对应的地址我们称作 canonical address。
那么处于 canonical address 空洞 :0x0000 7FFF FFFF F000 - 0xFFFF 8000 0000 0000 范围内的地址的高 16 位 不全为 0 也不全为 1。如果某个虚拟地址落在这段 canonical address 空洞区域中 , 那就是既不在用户空间 , 也不在内核空间 , 肯定是非法访问了 。
未来我们也可以利用这块 canonical address 空洞 , 来扩展虚拟内存地址的范围 , 比如扩展到 56 位 。
在我们理解了 canonical address 这个概念之后 , 我们再来看下 64 位 Linux 系统下的真实虚拟内存空间布局情况:

文章插图
从上图中我们可以看出 64 位系统中的虚拟内存布局和 32 位系统中的虚拟内存布局大体上是差不多的 。主要不同的地方有三点:
- 就是前边提到的由高 16 位空闲地址造成的canonical address 空洞 。在这段范围内的虚拟内存地址是不合法的 , 因为它的高 16 位既不全为 0 也不全为 1 , 不是一个 canonical address , 所以称之为 canonical address 空洞 。
- 在代码段跟数据段的中间还有一段不可以读写的保护段 , 它的作用是防止程序在读写数据段的时候越界访问到代码段 , 这个保护段可以让越界访问行为直接崩溃 , 防止它继续往下运行 。
- 用户态虚拟内存空间与内核态虚拟内存空间分别占用 128T , 其中低128T 分配给用户态虚拟内存空间 , 高 128T 分配给内核态虚拟内存空间 。
经验总结扩展阅读
- 神话中高要一步一步往上爬是第几集?
- 神话一步一步爬到最高是几集?
- 总以为她会永远陪我一步一步慢慢走是什么歌
- 爱情不会一步到位而是会经过颇多挫折才圆满的星座
- Dubbo 03: 直连式 + 接口工程
- 一篇文章带你了解热门版本控制系统——Git
- 一篇文章带你了解网页框架——Vue简单入门
- 一直在等待爱却不敢主动迈出一步的星座
- 我用canvas带你看一场流星雨
- 一篇文章带你掌握MyBatis简化框架——MyBatisPlus
