技术编程为什么 Linux 需要虚拟内存( 二 )
本文插图
page-fault
图 4 - 虚拟内存的缺页中断
因为主内存的空间是有限的 , 当主内存中不包含可以使用的空间时 , 操作系统会从选择合适的物理内存页驱逐回磁盘 , 为新的内存页让出位置 , 选择待驱逐页的过程在操作系统中叫做页面替换(Page Replacement) 。 缺页中断和页面替换技术都是操作系统调页算法(Paging)的一部分 , 该算法的目的就是充分利用内存资源作为磁盘的缓存以提高程序的运行效率 。
内存管理
虚拟内存可以为正在运行的进程提供独立的内存空间 , 制造一种每个进程的内存都是独立的假象 , 在 64 位的操作系统上 , 每个进程都会拥有 256 TiB 的内存空间 , 内核空间和用户空间分别占 128 TiB[^5] , 部分操作系统使用 57 位虚拟地址以提供 128 PiB 的寻址空间[^6] 。 因为每个进程的虚拟内存空间是完全独立的 , 所以它们都可以完整的使用 0x0000000000000000 到 0x00007FFFFFFFFFFFF 的全部内存 。
本文插图
virtual-memory-space
图 5 - 操作系统的虚拟内存空间
虚拟内存空间只是操作系统中的逻辑结构 , 就像我们上面说的 , 应用程序最终还是需要访问物理内存或者磁盘上的内容 。 因为操作系统加了一个虚拟内存的中间层 , 所以我们也需要为进程实现地址翻译器 , 实现从虚拟地址到物理地址的转换 , 页表是虚拟内存系统中的重要数据结构 , 每一个进程的页表中都存储了从虚拟内存到物理内存页的映射关系 , 为了存储 64 位操作系统中 128 TiB 虚拟内存的映射数据 , Linux 在 2.6.10 中引入了四层的页表辅助虚拟地址的转换[^7] , 在 4.11 中引入了五层的页表结构[^8] , 在未来还可能会引入更多层的页表结构以支持 64 位的虚拟地址 。
本文插图
four-level-page-tables
图 6 - 四层页表结构
在如上图所示的四层页表结构中 , 操作系统会使用最低的 12 位作为页面的偏移量 , 剩下的 32 位会分四组分别表示当前层级在上一层中的索引 , 所有的虚拟地址都可以用上述的多层页表查找到对应的物理地址 。
因为有多层的页表结构可以用来转换虚拟地址 , 所以多个进程可以通过虚拟内存共享物理内存 。 我们在 为什么 Redis 快照使用子进程 一文中介绍的写时复制就利用了虚拟内存的这个特性 , 当我们在 Linux 中调用 fork 创建子进程时 , 实际上 只复制了父进程的页表 。 如下图所示 , 父子进程会通过不同的页表指向相同的物理内存:
本文插图
process-shared-memory
图 7 - 进程间共享内存
虚拟内存不仅可以在 fork 时用于共享进程的物理内存 , 提供写时复制的机制 , 还能共享一些常见的动态库减少物理内存的占用 , 所有的进程都可能调用相同的操作系统内核代码 , 而 C 语言程序也会调用相同的标准库 。
除了能够共享内存之外 , 独立的虚拟内存空间也会简化内存的分配过程 , 当用户程序向操作系统申请堆内存时 , 操作系统可以分配几个连续的虚拟页 , 但是这些虚拟页可以对应到物理内存中不连续的页中 。
内存保护
操作系统中的用户程序不应该修改只读的代码段 , 也不应该读取或者修改内核中的代码和数据结构或者访问私有的以及其他的进程的内存 , 如果无法对用户进程的内存访问进行限制 , 攻击者就可以访问和修改其他进程的内存影响系统的安全 。
- 前有iPhone 12,后有Mate 40,为什么我却攥着中兴天机Axon 20 5G不放
- 机核网|为什么我觉得《刺客信条》越来越差了:游戏性篇
- 麦田军事观察|印度抨击法国公司拒绝转让核心技术啥意义?不知花钱买不来现代化
- 沈潮汐|扬言基建技术超越中国,2天后愣住了,印度3天时间搭好一座桥
- 量子科技,爆发!有项关键技术中国已领先世界
- 做你一辈子的蜡笔|西方为什么不假思索的污蔑中国?因为我们的这个错误!
- 暖日科技盈如|这到底是为什么?,俄罗斯华人给出劝告:最好别跟俄罗斯女孩结婚
- 什么值得买|为什么要精养信用卡?因为信用卡背后有你想象不到的财富!
- |为什么每一年的高考试卷,要安排在监狱里面印刷?原因你可能不信
- 王者荣耀手游|王者荣耀:为什么蜜橘之夏在返场中得票这么低?知道原因后网友直呼活该!