Linux虚拟内存,你理解到位了?

💡 原文中文,约4100字,阅读约需10分钟。
📝

内容提要

本文介绍了Linux虚拟内存的概念、原理和应用。虚拟内存通过地址转换解决了多进程访问内存冲突的问题,通过分页和页表实现虚拟内存与物理内存的映射。虚拟内存还有助于进程内存管理、数据共享和通过SWAP技术扩充内存。文章还提到了常见问题和管理命令。

🔎

延伸解读

虚拟内存如何“欺骗”进程

文章用 P1、P2 进程的例子说明,操作系统让每个进程都以为自己独占全部内存,实际只分配虚拟地址序号,真正使用时才映射到物理内存。这种“欺骗”手段正是虚拟内存的核心:进程无需关心物理地址,操作系统通过页表在背后完成重定向,甚至多个进程共享同一物理页时也互不知情。

页表与缺页中断的配合

为减少映射表开销,系统以 4K 为单位分页,4G 内存只需约 8M 页表,并采用多级页表进一步压缩。CPU 中的 MMU 负责地址翻译,利用局部性原理缓存命中率可达 98%。若访问的物理地址尚未分配,则触发缺页中断,由内核在中断处理中分配物理页,完成虚拟到物理的映射。

SWAP 是扩充也是性能代价

当物理内存不足时,Linux 可将暂时不用的内存数据放到磁盘 SWAP 分区,让进程以为拥有更多内存。但文章提醒,频繁换入换出会大量占用 CPU、降低系统效率。因此可通过 vm.swappiness=0 让系统尽量少用 swap,或用 swapoff 直接禁用,需根据实际负载权衡。

看 VIRT 不如看 RES

用 top 查看 Java 进程时,VIRT 列可能显示占用大量虚拟内存,但这并不代表真实消耗。文章解释,Java 通过 Glibc Arena 内存池分配了大量虚拟内存却未必使用,读取文件也会映射为虚拟内存,每个线程栈默认占 1M 虚拟内存。判断实际物理内存占用应看 RES 列,避免被 VIRT 误导。

❓

Q&A

Linux虚拟内存到底是什么?为什么需要它?

虚拟内存是操作系统中的一种内存管理技术,它通过地址转换让每个进程都以为自己独占全部内存,从而解决多进程同时访问内存的冲突问题。操作系统为每个进程维护虚拟地址到物理地址的映射,进程无需关心实际物理内存位置。

虚拟内存是如何通过分页和页表工作的?

操作系统将物理内存划分为固定大小的页(通常4K),并为每个进程维护页表,记录虚拟页到物理页的映射。当进程访问虚拟地址时,CPU中的内存管理单元(MMU)根据页表将其转换为物理地址。如果物理页尚未分配,会触发缺页中断,由内核分配物理内存并更新页表。

虚拟内存除了解决冲突还有什么好处?

虚拟内存还带来三个主要好处:1) 进程内存管理:每个进程看到连续地址空间,简化编程,同时通过页表权限位实现内存安全;2) 数据共享:多个进程的虚拟地址可映射到同一物理页,方便共享库和共享内存;3) 扩充内存:通过SWAP技术将不常用内存数据暂存磁盘,使进程可用内存超过物理内存限制。

为什么32位系统最大只支持4GB内存?

32位CPU有32条地址总线,每条总线可表示0或1,因此可访问的地址空间为2^32字节,即4GB。所以32位系统最大只能使用4GB物理内存,插入更大内存也无法被CPU访问。64位系统则突破此限制,但实际支持的最大内存还受操作系统限制,例如Linux目前支持最大256GB。

Java进程在top命令中VIRT列占用很高,是内存泄漏吗?

不一定。VIRT列表示进程使用的虚拟内存总量,Java进程由于使用Glibc的Arena内存池分配了大量虚拟内存但并未实际使用,且每个线程栈默认占用1M虚拟内存,所以VIRT值会很高。真实占用的物理内存应查看RES列,RES才是实际映射到物理内存的大小。

如何查看和管理Linux系统的虚拟内存?

可以使用free、vmstat命令查看系统整体内存状态,cat /proc/meminfo查看详细内存信息;使用pmap pid查看特定进程的虚拟内存分布;通过sysctl vm或直接读写/proc/sys/vm/下的文件修改内存配置;使用swapoff禁用SWAP,或设置vm.swappiness=0减少SWAP使用。

🏷️

标签

➡️

继续阅读