1. 引言
无论是 windows 系统还是 linux 操作系统,在硬盘上都有一块虚拟内存的空间。
无论你使用的是哪个系统,都存在一个问题,那就是到底虚拟内存的空间需要多大呢?虚拟内存又是什么呢?
本文就来详细介绍一下。
2. 什么是虚拟内存
自从 80386 CPU 以来,硬件提供了对操作系统分页机制的支持,其作用是让每个进程都拥有独立的完整内存地址空间,每个进程在访问内存时提供的地址不再是直接指向物理内存的物理地址,而变成了虚拟地址,由内存管理单元维护一个虚拟地址到物理地址的映射关系。
但是,这样会出现一个问题,那就是如果我们安装了 4GB 大小的物理内存,此时只运行两个程序,每个程序都需要占用 4GB 内存空间,显然我们的内存是不够的,操作系统为了解决这个问题,实现了将内存打散为 4KB 为单位的小块,即使这两个都需要 4GB 的进程同时运行,也没关系,只要将他们需要的若干块载入内存,将他们暂时不需要的内存块存储在磁盘上,就可以保证他们的顺利运行,因为事实上进程通常运行所需的内存空间是很少的,其大部分内存都可以被置换到硬盘上,而相对廉价的硬盘空间就显得没那么珍贵了。
上面说的用来存储暂时不使用的内存分页的磁盘空间就是操作系统的虚拟内存空间,也就是 linux 的 swap 空间,当进程需要访问的内存还没有被载入到物理内存中时,就会触发一个操作系统的软中断,名为“缺页中断”,操作系统会将对应的页从虚拟内存中置换到物理内存上,然后再返回到用户程序中继续执行。
在很多现代操作系统中,很多系统都支持休眠功能,就是在计算机再次开启时,能让计算机维持关机前完整状态的一种机制,他是通过将内存的所有信息全部保存在硬盘上来实现的,这个功能使用的磁盘空间也是操作系统的虚拟内存。
3. windows 与 linux 内存的分配机制
在 windows 和 linux 系统中,内存都被分为堆、栈、全局静态存储区、常量区、代码区。
这其中,只有堆内存空间是用户可以自由申请和使用的。
在 windows 中,内存必须先执行 VirtualAlloc Api 进行申请内存,操作系统会在虚拟地址空间中保留一块空间供发起申请的进程使用,这个过程称之为“保留”,随后,操作系统将这块虚拟地址空间与物理内存进行映射,从而完成内存的分配,这个过程被称为“提交”,这样,在操作系统的完整内存空间中就分配出了一块仅供发起申请的进程使用的内存空间。
linux 的内存分配策略与 windows 非常不同,linux 采取懒惰式分配的原则,当进程发起堆空间内存分配的申请时,操作系统仅仅是在进程信息上扩大其所需要的内存值大小,也就是 top 命令中进程 VIRT 属性的值,实际上并不进行内存的分配。
当进程使用到尚未被分配的内存时,由于这部分内存不在物理内存中,就会触发操作系统缺页中断,此时,操作系统检测到内存尚未分配,才会为进程分配这部分内存空间,并置换入物理内存。
显然,windows 的分配策略的出发点在于最大限度的满足进程的需求,避免在进程执行过程中出现意外的内存不足问题,因为在内存分配过程中,如果因为操作系统实际内存不足造成了内存分配失败,对于申请内存的进程而言,这是可预期的异常,而在其他正常执行过程中,意外的内存不足是不应该出现的。
但这样做的代价就是让进程可能出现“占着茅坑不拉屎”的现象,很多进程采用的是预分配的池化策略,为了避免在进程工作过程中反复与内核交互进行内存划分的性能影响,这类进程采用整块申请内存,申请后逐步在已分配内存中使用的策略,这样的策略下,进程申请分配的内存要远大于实际执行时所使用的内存,在 windows 系统中,这类进程就会占用过多的内存,而在 linux 系统中,他们申请的内存则只体现在了 VIRT 属性上,并不会占用实际的内存。
当然,实际上操作系统的内存分配机制远比上述简单的机制要复杂的多,上面只是做一个直观的介绍。
4. 虚拟内存多大够用
内存对于计算机的运行起着至关重要的作用,作为“磁盘缓存”的虚拟内存空间也同样非常重要。
那么,究竟多大的虚拟内存空间才够用呢?
对于追求性能的服务器应用场景,通常是不建议使用虚拟内存的,因为与内存读写的高性能相比,磁盘读写显得性能过低,因此我们是彻底不希望服务器应用向磁盘交换地址空间的,所以对于服务器来说,虚拟内存通常会设置为 0,除非使用的是高性能的配有 SSD 的服务器。
4.1. redhat 的建议值
对于普通用户来说,RedHat 文档上有一个简单的标准可供参考:
不同内存大小对应的 swap 空间建议大小
物理内存大小 | swap 空间 | 需要休眠的建议 |
⩽ 2GB | 2 倍于物理内存 | 3 倍于物理内存 |
2GB – 8GB | 等于物理内存 | 2 倍于物理内存 |
8GB – 64GB | 4GB以上 | 1.5 倍于物理内存 |
> 64GB | 4GB以上 | 不建议开启休眠功能 |
4.2. ubuntu 的建议值
ubuntu 文档上给出了更为详细的建议值,但总体与 redhat 建议值是相同的。
不同内存大小对应的 swap 空间建议大小
物理内存 | swap 空间 | 需要休眠 | 最大不要超过 |
256MB | 256MB | 512MB | 512MB |
512MB | 512MB | 1024MB | 1024MB |
1024MB | 1024MB | 2048MB | 2048MB |
1GB | 1GB | 2GB | 2GB |
2GB | 1GB | 3GB | 4GB |
3GB | 2GB | 5GB | 6GB |
4GB | 2GB | 6GB | 8GB |
5GB | 2GB | 7GB | 10GB |
6GB | 2GB | 8GB | 12GB |
8GB | 3GB | 11GB | 16GB |
12GB | 3GB | 15GB | 24GB |
16GB | 4GB | 20GB | 32GB |
24GB | 5GB | 29GB | 48GB |
32GB | 6GB | 38GB | 64GB |
64GB | 8GB | 72GB | 128GB |
128GB | 11GB | 139GB | 256GB |
256GB | 16GB | 272GB | 512GB |
512GB | 23GB | 535GB | 1TB |
1TB | 32GB | 1056GB | 2TB |
2TB | 46GB | 2094GB | 4TB |
4TB | 64GB | 4160GB | 8TB |
8TB | 91GB | 8283GB | 16TB |
5. 调整 swap 使用优先级
在 linux 系统中,系统允许用户配置对虚拟内存使用的优先级,可以通过 /proc/sys/vm/swappiness
文件查看当前值。
这个值是一个 0 到 100 的数,0 表示最大限度使用物理内存,100 则表示最大限度使用虚拟内存。
由于磁盘读写性能与内存读写相比十分低下,因此建议将这个数字设置偏小一些。
具体的设置方法是编辑 /etc/sysctl.conf
文件,添加:
vm.swappiness=10
保存后,重启即可生效。
6. 调整 swap 分区大小
windows 环境下,可以在计算机属性的高级选项卡中,找到相应的设置,包括可以将虚拟内存文件保存在哪个磁盘,以及虚拟内存文件的大小等参数。
在 linux 系统上,需要执行以下步骤进行 swap 空间的调整:
6.1. 新建分区
执行 dd 命令新建磁盘分区:
dd if=/dev/zero of=/host/disks/swap.disk bs=1024 count=2048000
这样我们就创建一个 2GB 的 swap 分区。
6.2. 关闭当前正在使用的 swap 分区
swapoff -a
6.3. 将新分区设置为 swap 分区
/sbin/mkswap /host/disks/swap.disk
/sbin/swapon /host/disks/swap.disk
6.4. 自动启动 swap 分区
在 /etc/fstab
文件中添加:
/host/disks/swap.disk swap swap defaults 0 0
6.5. 查看内存信息
可以通过 free -m
命令查看内存信息。
此处有图片 2
8. 参考资料
https://access.redhat.com/documentation/en-us/red\_hat\_enterprise\_linux/6/html/installation\_guide/s2-diskpartrecommend-ppc#id4394007。https://help.ubuntu.com/community/SwapFaq。
。
。