Swap

来自 Arch Linux 中文维基

本文介绍了GNU/Linux上的交换空间和分页。它将教您如何创建或启用交换分区或交换文件。

以下引用来自于关于 Linux Swap 空间:

Linux 将物理内存分为内存段,叫做页面。交换是指内存页面被复制到预先设定好的硬盘空间(叫做交换空间)的过程,目的是释放这份内存页面。物理内存和交换空间的总大小是可用的虚拟内存的总量。

swap 支持由 Linux 内核和来自 util-linux 软件包的用户空间实用程序提供。

交换空间[编辑 | 编辑源代码]

交换空间可以是磁盘的一个分区,也可以是一个文件。用户可以在安装时或安装后的任何时候创建交换空间。交换空间有两种用途:第一,是将虚拟内存扩大到超过已安装的物理内存(RAM)的容量;第二,是用于 suspend-to-disk 支持。

使用swap扩展您的虚拟内存是否有好处取决与您的物理内存。如果物理内存不足以支撑您日常使用全部的程序的话(体现在日常使用时内存满了导致的卡顿,死机),使用swap也许会对您有些帮助。这样可以避免 out of memory conditions,Linux内核OOM Killer机制将尝试通过杀进程的方式来自动释放内存。如果您想让虚拟内存足够使用,请添加相应的差值(或更多)作为交换空间。

启用交换的最大缺点是性能较低,请参阅:#性能优化。因此,启用swap是个人喜好问题:当物理内存用完时,有些人更喜欢杀死程序而不是启用交换,而另一些人更喜欢启用交换和较慢的系统。

注意: 连续的交换文件和交换分区之间没有性能之别,两者的处理方式是一样的。

要检查交换空间的状态,使用

$ swapon --show

或者显示物理内存以及交换使用情况:

$ free -h

交换分区[编辑 | 编辑源代码]

交换分区可以用大多数 GNU/Linux 分区工具(例如 fdisk, cfdisk) 创建。交换分区在 MBR 中的类型为 82,在 GPT 中的类型为 0657FD6D-A4AB-43C4-84E5-0933C84B4F4F

要将分区设置为Linux交换分区,请使用 mkswap(8) 命令。例如:

# mkswap /dev/sdxy
警告: 指定分区上的所有数据会丢失。

想要启用一个设备作为交换分区:

# swapon /dev/sdxy

想要启动时自动启用交换分区,添加一个条目到 /etc/fstab:

UUID=device_UUID none swap defaults 0 0

UUID可以通过以下命令获得:

lsblk -no UUID /dev/sdxy

其中 device_UUID 是交换分区的 UUID 。有关文件语法,请参见 fstab

提示:UUID 和 LABEL 应该比使用由内核给出的设备名称更受青睐,因为设备顺序可能在将来发生变化。详细信息,请参见 fstab
注意: 如果交换分区位于使用 GPT 的设备上,fstab 配置项是可选的,请参考 #通过 Systemd 激活
警告: 在使用 madam 进行 RAID 设置时,如果开启 swapon 命令的 discard 参数,将导致系统在启动和运行时锁定。

通过 Systemd 激活[编辑 | 编辑源代码]

systemd 通过两种机制来激活 swap 分区。两种都是 /usr/lib/systemd/system-generators 内的可执行文件。generators 在启动时运行并为 mounts 创建本地 systemd 单元。第一种机制是通过 systemd-fstab-generator 读取 fstab 来生成单元,包括 swap 单元。 第二种机制是通过 systemd-gpt-auto-generator 检查根磁盘来生成单位。这个机制仅在 GPT 磁盘上运行,并可以根据交换分区的GUID类型对其进行标识。详细信息,请参阅 systemd#GPT partition automounting

关闭交换分区[编辑 | 编辑源代码]

使用下面的命令关闭交换分区:

# swapoff /dev/sdxy

也可以使用 -a 参数来关闭所有的交换分区。

因为 swap 通过 systemd 管理,因此会在下一次系统启动时再次激活。要永久禁用该特性,运行 systemctl --type swap 来查找 .swap 单元,然后 mask 它。

交换文件[编辑 | 编辑源代码]

相比于使用一个磁盘分区作为交换空间,使用交换文件可以更方便地随时调整大小或者移除。当磁盘空间有限(例如常规大小的SSD)时,使用交换文件更加理想。

注意: 自Linux内核版本5.0起,Btrfs支持交换文件,但有限制。有关更多信息,请参见 Btrfs#交换文件

建立交换文件[编辑 | 编辑源代码]

注意: 如果您使用Btrfs,请按照 Btrfs#交换文件 初始化交换文件,不要使用下面的方式。

使用 dd 去创建一个由你自己指定大小的交换文件。例如,创建一个 512 MiB 的交换文件:

# dd if=/dev/zero of=/swapfile bs=1M count=512 status=progress
注意: 使用 dd to allocate a swap file is the most portable solution,有关更多信息,请参见 swapon(8) § Files with holes

为交换文件设置权限(交换文件全局可读是一个巨大的本地漏洞):

# chmod 0600 /swapfile

创建正确大小的文件后,将其格式化用来作为交换文件:

# mkswap -U clear /swapfile

启用交换文件:

# swapon /swapfile

最后,编辑 /etc/fstab,在为交换文件添加一个条目:

/etc/fstab
/swapfile none swap defaults 0 0

有关更多信息,请参见 fstab#Usage.

注意: 交换文件必须由文件系统上的位置指定,而不是由UUID或标签指定。

删除交换文件[编辑 | 编辑源代码]

如果要删除一个交换文件,必须先停用它。

作为root运行:

# swapoff /swapfile

然后即可删除它:

# rm -f /swapfile

最后从 /etc/fstab 中删除相关条目

在内存中的压缩块设备[编辑 | 编辑源代码]

如果使用了交换文件或分区,默认会支持 zswap。如果使用 zram 内存压缩块设备,就不再需要交换文件或分区。zramzswap 的区别请参考 Improving performance#zram or zswap

交换加密[编辑 | 编辑源代码]

查看 dm-crypt/交换分区加密英语dm-crypt/Swap encryption

性能优化[编辑 | 编辑源代码]

交换操作通常比直接访问RAM中的数据慢得多。完全禁用交换以提高性能有时会导致性能下降,因为它会减少VFS缓存的可用内存,从而导致更频繁地使用宝贵的磁盘I/O。

可以调整交换值以提高性能:

交换值(Swappiness)[编辑 | 编辑源代码]

swappiness sysctl 参数代表了内核对于交换空间的喜好(或厌恶)程度。Swappiness 的值可以是 0 到 200 之间 (在Linux内核版本低于5.8时最大值为100),默认值为60。设置这个参数为较低的值会减少内存的交换,从而提升一些系统上的响应度。较高值会导致内核尝试使用交换空间,而值100意味着各IO的喜好(或厌恶)程度相等。众所周知,在许多系统中,在足够的内存上使用较低的值可以提高响应能力。

要查看当前交换值(Swappiness),请执行以下操作:

$ sysctl vm.swappiness

此外,可以读取文件 /sys/fs/cgroup/memory/memory.swappiness(仅适用于 cgroup v1) 或 /proc/sys/vm/swappiness 以获得原始整数值。

要临时设置交换值(Swappiness),请执行以下操作:

# sysctl -w vm.swappiness=10

要永久设置交换值,请创建sysctl.d(5)配置文件。例如:

/etc/sysctl.d/99-swappiness.conf
vm.swappiness=10

To have the boot loader set swappiness when loading the kernel, add a kernel parameter, e.g. sysctl.vm.swappiness=10.

要测试和了解这可能起作用的原因,请查看此文章.

VFS 缓存压力[编辑 | 编辑源代码]

vm.vfs_cache_pressure 是另外一个影响交换性能的 sysctl 参数,这个参数控制内核回收 VFS 缓存的程度,增大数值会增加回收 VFS 缓存的频率[1]. 更多信息请阅读 Linux kernel documentation

优先级[编辑 | 编辑源代码]

如果你有多个交换文件或交换分区,你应该考虑给它们各自分配一个优先级值(0 到 32767)。在使用较低优先级的交换区域之前,系统会优先使用较高优先级的交换区域。例如,如果你有一个较快的磁盘 (/dev/sda) 和一个较慢的磁盘 (/dev/sdb),给较快的设备分配一个更高的优先级。优先级可以在 fstab 中通过 pri 参数指定:

/dev/sda1 none swap defaults,pri=100 0 0
/dev/sdb2 none swap defaults,pri=10  0 0

或者通过 swapon 的 --priority 参数:

# swapon --priority 100 /dev/sda1

如果两个或更多的区域有同样的优先级,并且它们都是可用的最高优先级,页面会按照循环的方式在它们之间分配。

分片[编辑 | 编辑源代码]

不需要使用 RAID 提高交换的性能,只要在 /etc/fstab 中给交换设备设置相同的优先级,内核会将交换分片到多个设备。详情请参考 Software-RAID 指南