1. 简介

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

1.1 交换空间

交换空间通常是一个磁盘分区(交换分区),但是也可以是一个文件(交换文件)。用户可以在安装 Arch Linux 的时候创建交换空间,或者在安装后的任何时间建立交换空间。交换空间可用于两个目的:

  • 将虚拟内存扩大到超过已安装的物理内存的容量。
  • 用于支持系统休眠。

电脑系统目前主要有三种挂起方式:

  1. 睡眠(Suspend to RAM):将机器中大多数和RAM不相关的部件断电,电脑状态仅仅保存在RAM中。关闭多数外围设备,保留鼠标键盘等少数外围设备,以对用户操作进行快速响应。
  2. 休眠(Suspend to Disk):将机器内容保存至交换空间并完全断电。再次开机时从硬盘读取交换空间进内存,恢复运行状态。和睡眠不同,休眠时不会耗电。
  3. 混合休眠(Suspend to Both):将电脑状态保存进交换空间,但并不对电脑断电,而是引用睡眠机制,从而使未掉电的电脑能从内存中恢复。如果电脑掉电(断电且电池耗尽),系统也可以从硬盘的交换空间中恢复,尽管比从内存中恢复慢一些。

2. 交换分区

交换分区可以用大多数 GNU/Linux 分区工具(例如 fdisk, cfdisk 或图形化工具 GParted) 创建。

2.1 设置交换分区

将分区设置为交换分区:

1
sudo mkswap /dev/sdxy       # /dev/sdxy 分区上的所有数据会丢失

2.2 启用交换分区

  • 临时启用
1
sudo swapon /dev/sdxy
  • 永久启用

首先查看交换分区的 UUID:

1
lsblk -no UUID /dev/sdxy

然后添加一个条目到 /etc/fstab 文件:

1
2
# /etc/fstab
UUID=dev_sdxy_UUID none swap defaults 0 0 # dev_sdxy_UUID 为查到的 /dev/sdxy 的 UUID

这样配置后,以后每次启动系统时都会启用 /dev/sdxy 交换分区。如果想要此次不重启就启用,则可以用「临时启用」方法。

2.3 关闭交换分区

  • 临时关闭
1
sudo swapoff /dev/sdxy
  • 永久关闭

首先查看交换分区的 UUID:

1
lsblk -no UUID /dev/sdxy

然后注释掉 /etc/fstab 文件中对应的条目:

1
2
# /etc/fstab
# UUID=dev_sdxy_UUID none swap defaults 0 0

3. 交换文件

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

3.1 手动方式

  • 创建交换文件
1
2
# 创建一个 512 MB 的交换文件
sudo dd if=/dev/zero of=/swapfile bs=1M count=512 status=progress
  • 为交换文件设置权限
1
2
3
# 设置 600 权限是为了防止交换文件全局可读
# 交换文件全局可读是一个巨大的本地漏洞
sudo chmod 600 /swapfile
  • 格式化交换文件
1
sudo mkswap /swapfile
  • 启用交换文件
  1. 临时启用
1
sudo swapon /swapfile
  1. 永久启用

添加一个条目到 /etc/fstab 文件:

1
2
# /etc/fstab
/swapfile none swap defaults 0 0

这样配置后,以后每次启动系统时都会启用 /swapfile 交换分区。如果想要此次不重启就启用,则可以用「临时启用」方法。

  • 关闭交换文件

首先要停用它:

1
sudo swapoff /swapfile

然后,如果 /etc/fstab/ 中有对应条目,需要注释/删除掉:

1
2
# /etc/fstab
# /swapfile none swap defaults 0 0

最后,如果确定交换文件 /swapfile 不再使用,也可以删除:

1
sudo rm -f /swapfile

3.2 自动方式

Linux 内核提供了两个内核模块用于压缩缓存页,再将压缩后的缓存页换入内存/交换空间,从而提高内存/交换空间的利用率。由于其需要先对缓存页进行压,因此会占用更多 CPU 资源,降低一些响应性能。

  • zram:在内存中提供了一个压缩块,内存可以保存更多的数据,代价是消耗更多的 CPU 。

它仍然比硬盘上的交换空间快得多。若一个系统经常使用交换空间,使用 zram 可以提高响应。使用 zram 也可以减少对磁盘的读写,当交换空间被设置到固态硬盘时,这可以增加固态硬盘的寿命。

  • zswap:可以带来相似的益处(和相似的代价)。两者不同的是 zswap 将页面压缩后换入交换空间,而 zram 则换入内存。

因此,相较于 zswap,zram 的响应是更快的。

3.2.1 zram-generator

zram-generator 项目使用 Rust 编写,主要用于创建 zram 设备,即在内存中划分出一个或多个交换分区,用于缓存压缩后的页面。

  • 首先安装 zram-generator。
1
sudo pacman -S zram-generator
  • 然后创建并编缉配置文件 /etc/systemd/zram-generator.conf

该配置文件模板如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# This file is part of the zram-generator project
# https://github.com/systemd/zram-generator

[zram0]
# This section describes the settings for /dev/zram0.
#
# The maximum amount of memory (in MiB). If the machine has more RAM
# than this, zram device will not be created.
#
# "host-memory-limit = none" may be used to disable this limit. This
# is also the default.
host-memory-limit = 9048

# The fraction of memory to use as ZRAM. For example, if the machine
# has 1 GiB, and zram-fraction=0.25, then the zram device will have
# 256 MiB. Values in the range 0.10–0.50 are recommended.
#
# The default is 0.5.
zram-fraction = 0.10

# The maximum size of the zram device (in MiB).
#
# If host-memory times zram-fraction is greater than this,
# the size will be capped to this amount;
# for example, on a machine with 2 GiB of RAM and with zram-fraction=0.5,
# the device would still be 512 MiB in size due to the limit below.
#
# The default is 4096.
max-zram-size = 512

# The compression algorithm to use for the zram device,
# or leave unspecified to keep the kernel default.
compression-algorithm = lzo-rle

[zram1]
# This section describes the settings for /dev/zram1.
#
# host-memory-limit is not specified, so this device will always be created.

# Size the device to a tenth of RAM.
zram-fraction = 0.1

# The file system to put on the device. If not specified, ext2 will be used.
fs-type = ext2

# Where to mount the file system. If a mount point is not specified,
# the device will be initialized, but will not be used for anything.
mount-point = /run/compressed-mount-point

比如,我只为自己的系统创建一个 /dev/zram0 压缩缓存块:

1
2
[zram0]
zram-fraction = 0.50 # 压缩缓存块最大占用一半的内存
  • 最后重启系统。

3.2.2 systemd-swap

systemd-swap 项目目前提交频率低,且 zram 覆盖了大多数用户的需求,故其作者建议用 zram-generator 来替代该项目。

systemd-swap 是一个脚本,用于从 zram 交换、交换文件和交换分区创建混合交换空间。具体使用参见它的代码仓库说明:systemd-swap

4. 查看交换空间信息

4.1 查看所有交换空间使用情况

1
swapon --show

4.2 查看 zramX 设备状态

1
systemctl status systemd-zram-setup@zramX.service   # X 为编号

4.3 查看 zramX 设备支持的压缩算法

1
cat /sys/block/zramX/comp_algorithm

【注】目录 /sys/block/zramX 下存储了很多 zramX 设备的信息,除了 comp_algorithm 外,还有很多其它的信息文件。每个信息文件及其描述的信息参见:sysfs-block-zram

附录

参考资料: