搜索
首页系统教程LINUXLinux虚拟内存,你理解到位了?

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

Feb 05, 2024 pm 12:42 PM
linuxlinux教程linux系统linux命令外壳脚本嵌入式linux良好的许可证linux入门linux学习

前言

最近,组内有一个我非常期待的分享主题:”Linux的虚拟内存”。某天晚上加班时,我们在讨论虚拟内存的概念时,我们的领导发现几位同事对虚拟内存的理解不够清晰,于是特意为这位同事挑选了这个主题(笑)。

之前,我对操作系统的概念有一些了解,但毕业后我对自己大学四年的计算机专业的荒废感到有些懊悔。因此,在工作之余,我抽出时间观看了哈尔滨工业大学在网易云课堂上的操作系统公开课,还阅读了一本讲解操作系统概念较浅的书籍《Linux内核设计与实现》。此外,去年我使用C语言编写了一个简单的服务器,深入了解了更多系统底层的知识。这些知识让我对应用层的知识有了更好的掌握,并在最近一次故障排查中给予了我很大的帮助。

前几天,另一位同事向我提出了另一个与虚拟内存相关的问题,我才意识到对虚拟内存的理解还不够深刻,一些概念甚至存在矛盾。因此,我翻阅了一些资料,并重新整理了这些知识,希望下次在实际应用时能更加流畅。

起源


虚拟内存

毫无疑问,虚拟内存绝对是操作系统中最重要的概念之一。我认为主要是因为内存在整个系统中的重要性地位。CPU速度非常快,但容量有限且功能单一,而其他的I/O硬件在各种花式功能方面都有支持,但相对于CPU来说它们速度较慢。因此,它们之间需要一种润滑剂作为缓冲,这就是内存发挥作用的地方。

在现代操作系统中,多任务已经成为标配。多任务并行大大提高了CPU的利用率,但也带来了多个进程对内存操作的冲突问题,而虚拟内存的概念就是为了解决这个问题。

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

上图是虚拟内存最简单也是最直观的解释。

操作系统有一块物理内存(中间的部分),有两个进程(实际会更多)P1 和 P2,操作系统偷偷地分别告诉 P1 和 P2,我的整个内存都是你的,随便用,管够。可事实上呢,操作系统只是给它们画了个大饼,这些内存说是都给了 P1 和 P2,实际上只给了它们一个序号而已。只有当 P1 和 P2 真正开始使用这些内存时,系统才开始使用辗转挪移,拼凑出各个块给进程用,P2 以为自己在用 A 内存,实际上已经被系统悄悄重定向到真正的 B 去了,甚至,当 P1 和 P2 共用了 C 内存,他们也不知道。

操作系统的这种欺骗进程的手段,就是虚拟内存。对 P1 和 P2 等进程来说,它们都以为自己占用了整个内存,而自己使用的物理内存的哪段地址,它们并不知道也无需关心。

分页和页表

虚拟内存是操作系统里的概念,对操作系统来说,虚拟内存就是一张张的对照表,P1 获取 A 内存里的数据时应该去物理内存的 A 地址找,而找 B 内存里的数据应该去物理内存的 C 地址。

我们知道系统里的基本单位都是 Byte 字节,如果将每一个虚拟内存的 Byte 都对应到物理内存的地址,每个条目最少需要 8字节(32位虚拟地址->32位物理地址),在 4G 内存的情况下,就需要 32GB 的空间来存放对照表,那么这张表就大得真正的物理地址也放不下了,于是操作系统引入了 页(Page)的概念。

在系统启动时,操作系统将整个物理内存以 4K 为单位,划分为各个页。之后进行内存分配时,都以页为单位,那么虚拟内存页对应物理内存页的映射表就大大减小了,4G 内存,只需要 8M 的映射表即可,一些进程没有使用到的虚拟内存,也并不需要保存映射关系,而且Linux 还为大内存设计了多级页表,可以进一页减少了内存消耗。操作系统虚拟内存到物理内存的映射表,就被称为页表

内存寻址和分配

我们知道通过虚拟内存机制,每个进程都以为自己占用了全部内存,进程访问内存时,操作系统都会把进程提供的虚拟内存地址转换为物理地址,再去对应的物理地址上获取数据。CPU 中有一种硬件,内存管理单元 MMU(Memory Management Unit)专门用来将翻译虚拟内存地址。CPU 还为页表寻址设置了缓存策略,由于程序的局部性,其缓存命中率能达到 98%。

以上情况是页表内存在虚拟地址到物理地址的映射,而如果进程访问的物理地址还没有被分配,系统则会产生一个缺页中断,在中断处理时,系统切到内核态为进程虚拟地址分配物理地址。

功能


虚拟内存不仅通过内存地址转换解决了多个进程访问内存冲突的问题,还带来更多的益处。

进程内存管理

它有助于进程进行内存管理,主要体现在:

  • 内存完整性:由于虚拟内存对进程的”欺骗”,每个进程都认为自己获取的内存是一块连续的地址。我们在编写应用程序时,就不用考虑大块地址的分配,总是认为系统有足够的大块内存即可。
  • 安全:由于进程访问内存时,都要通过页表来寻址,操作系统在页表的各个项目上添加各种访问权限标识位,就可以实现内存的权限控制。

数据共享

通过虚拟内存更容易实现内存和数据的共享。

在进程加载系统库时,总是先分配一块内存,将磁盘中的库文件加载到这块内存中,在直接使用物理内存时,由于物理内存地址唯一,即使系统发现同一个库在系统内加载了两次,但每个进程指定的加载内存不一样,系统也无能为力。

而在使用虚拟内存时,系统只需要将进程的虚拟内存地址指向库文件所在的物理内存地址即可。如上文图中所示,进程 P1 和 P2 的 B 地址都指向了物理地址 C。

而通过使用虚拟内存使用共享内存也很简单,系统只需要将各个进程的虚拟内存地址指向系统分配的共享内存地址即可。

SWAP

虚拟内存可以让帮进程”扩充”内存。

我们前文提到了虚拟内存通过缺页中断为进程分配物理内存,内存总是有限的,如果所有的物理内存都被占用了怎么办呢?

Linux 提出 SWAP 的概念,Linux 中可以使用 SWAP 分区,在分配物理内存,但可用内存不足时,将暂时不用的内存数据先放到磁盘上,让有需要的进程先使用,等进程再需要使用这些数据时,再将这些数据加载到内存中,通过这种”交换”技术,Linux 可以让进程使用更多的内存。

常见问题


在了解虚拟内存时,我也有过很多的问题。

32位和64位

最常见的就是 32位和64位的问题了。

CPU 通过物理总线访问内存,那么访问地址的范围就受限于机器总线的数量,在32位机器上,有32条总线,每条总线有高低两种电位分别代表 bit 的 1 和 0,那么可访问的最大地址就是 2^32bit = 4GB,所以说 32 位机器上插入大于 4G 的内存是无效的,CPU 访问不到多于 4G 的内存。

但 64位机器并没有 64位总线,而且其最大内存还要受限于操作系统,Linux 目前支持最大 256G 内存。

根据虚拟内存的概念,在 32 位系统上运行 64 位软件也并无不可,但由于系统对虚拟内存地址的结构设计,64位的虚拟地址在32位系统内并不能使用。

直接操作物理内存

操作系统使用了虚拟内存,我们想要直接操作内存该怎么办呢?

Linux 会将各个设备都映射到 /dev/ 目录下的文件,我们可以通过这些设备文件直接操作硬件,内存也不例外。在 Linux 中,内存设置被映射为 /dev/mem,root 用户通过对这个文件读写,可以直接操作内存。

JVM 进程占用虚拟内存过多

使用 TOP 查看系统性能时,我们会发现在 VIRT 这一列,Java 进程会占用大量的虚拟内存。

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

导致这种问题的原因是 Java 使用 Glibc 的 Arena 内存池分配了大量的虚拟内存并没有使用。此外,Java 读取的文件也会被映射为虚拟内存,在虚拟机默认配置下 Java 每个线程栈会占用 1M 的虚拟内存。具体可以查看 为什么linux下多线程程序如此消耗虚拟内存。

而真实占用的物理内存要看 RES (resident) 列,这一列的值才是真正被映射到物理内存的大小。

常用管理命令


我们也可以自己来管理 Linux 的虚拟内存。

查看系统内存状态

查看系统内存情况的方式有很多,freevmstat等命令都可输出当前系统的内存状态,需要注意的是可用内存并不只是 free 这一列,由于操作系统的 lazy 特性,大量的 buffer/cache 在进程不再使用后,不会被立即清理,如果之前使用它们的进程再次运行还可以继续使用,它们在必要时也是可以被利用的。

此外,通过 cat /proc/meminfo 可以查看系统内存被使用的详细情况,包括脏页状态等。详情可参见:/PROC/MEMINFO之谜。

pmap

如果想单独查看某一进程的虚拟内存分布情况,可以使用 pmap pid 命令,它会把虚拟内存各段的占用情况从低地址到高地址都列出来。

可以添加 -XX 参数来输出更详细的信息。

修改内存配置

我们也可以修改 Linux 的系统配置,使用 sysctl vm [-options] CONFIG 或 直接读写 /proc/sys/vm/ 目录下的文件来查看和修改配置。

SWAP 操作

虚拟内存的 SWAP 特性并不总是有益,放任进程不停地将数据在内存与磁盘之间大量交换会极大地占用 CPU,降低系统运行效率,所以有时候我们并不希望使用 swap。

我们可以修改 vm.swappiness=0 来设置内存尽量少使用 swap,或者干脆使用 swapoff 命令禁用掉 SWAP。

小结


虚拟内存的概念非常容易理解,但是它会衍生出来的一系列非常复杂的知识。本文只讲了些基本原理,略过了很多细节,比如虚拟内存寻址中段寄存器的使用,操作系统使用虚拟内存增强缓存、缓冲区的应用等,有机会单独拿出来说。

以上是Linux虚拟内存,你理解到位了?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:良许Linux教程网。如有侵权,请联系admin@php.cn删除
Linux软件的未来:Flatpak和Snap会替换本机桌面应用程序吗?Linux软件的未来:Flatpak和Snap会替换本机桌面应用程序吗?Apr 25, 2025 am 09:10 AM

多年来,Linux软件分布依赖于DEB和RPM等本地格式,并深深地根深蒂固。 但是,Flatpak和Snap已经出现,有望成为应用程序包装的通用方法。 本文考试

Linux和Windows处理设备驱动程序的区别有什么区别?Linux和Windows处理设备驱动程序的区别有什么区别?Apr 25, 2025 am 12:13 AM

Linux和Windows在处理设备驱动程序上的差异主要体现在驱动管理的灵活性和开发环境上。1.Linux采用模块化设计,驱动可以动态加载和卸载,开发者需深入理解内核机制。2.Windows依赖微软生态,驱动需通过WDK开发并签名认证,开发相对复杂但保证了系统的稳定性和安全性。

比较和对比Linux和Windows的安全模型。比较和对比Linux和Windows的安全模型。Apr 24, 2025 am 12:03 AM

Linux和Windows的安全模型各有优势。Linux提供灵活性和可定制性,通过用户权限、文件系统权限和SELinux/AppArmor实现安全。Windows则注重用户友好性,依赖WindowsDefender、UAC、防火墙和BitLocker保障安全。

Linux和Windows之间的硬件兼容性有何不同?Linux和Windows之间的硬件兼容性有何不同?Apr 23, 2025 am 12:15 AM

Linux和Windows在硬件兼容性上不同:Windows有广泛的驱动程序支持,Linux依赖社区和厂商。解决Linux兼容性问题可通过手动编译驱动,如克隆RTL8188EU驱动仓库、编译和安装;Windows用户需管理驱动程序以优化性能。

Linux和Windows之间虚拟化支持有哪些差异?Linux和Windows之间虚拟化支持有哪些差异?Apr 22, 2025 pm 06:09 PM

Linux和Windows在虚拟化支持上的主要区别在于:1)Linux提供KVM和Xen,性能和灵活性突出,适合高定制环境;2)Windows通过Hyper-V支持虚拟化,界面友好,与Microsoft生态系统紧密集成,适合依赖Microsoft软件的企业。

Linux系统管理员的主要任务是什么?Linux系统管理员的主要任务是什么?Apr 19, 2025 am 12:23 AM

Linux系统管理员的主要任务包括系统监控与性能调优、用户管理、软件包管理、安全管理与备份、故障排查与解决、性能优化与最佳实践。1.使用top、htop等工具监控系统性能,并进行调优。2.通过useradd等命令管理用户账户和权限。3.利用apt、yum管理软件包,确保系统更新和安全。4.配置防火墙、监控日志、进行数据备份以确保系统安全。5.通过日志分析和工具使用进行故障排查和解决。6.优化内核参数和应用配置,遵循最佳实践提升系统性能和稳定性。

很难学习Linux吗?很难学习Linux吗?Apr 18, 2025 am 12:23 AM

学习Linux并不难。1.Linux是一个开源操作系统,基于Unix,广泛应用于服务器、嵌入式系统和个人电脑。2.理解文件系统和权限管理是关键,文件系统是层次化的,权限包括读、写和执行。3.包管理系统如apt和dnf使得软件管理方便。4.进程管理通过ps和top命令实现。5.从基本命令如mkdir、cd、touch和nano开始学习,再尝试高级用法如shell脚本和文本处理。6.常见错误如权限问题可以通过sudo和chmod解决。7.性能优化建议包括使用htop监控资源、清理不必要文件和使用sy

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具