update 2022/09/20: 请注意,如果你是 btrfs 用户,请先确认内核版本大于 5.0,然后创建一个非快照子卷并禁用写时复制用于存储交换文件。禁用CoW 的方法是:

# chattr +C /path/to/swapsubvolume

请务必确认这三点:内核版本大于 5.0;新子卷,非快照;禁用写时复制。

另外,下文中提到的 mkinitcpio 是用于 archlinux 的工具,用于制作 initramfs。在不同发行版中默认的使用工具会不同。以 Debian 为例,使用的是 initramfs-tools。你需要修改 /etc/initramfs/initramfs.conf 或者添加配置和钩子到 /etc/initramfs/conf.d/etc/initramfs/conf-hooks.d,然后运行 update-initramfs -u 来重建并更新 initranfs 镜像。无论如何,所要做的就是让系统在引导阶段能够找到交换文件所处的位置,并能读出其中的数据以恢复到休眠前的状态。

同样的,如果你是 btrfs 用户,用 filefrag 得到的 physical_offset 也是不准确的。我非常建议阅读 archwiki 而不是我这篇可能过时的博文。


因为是电骡党,所以笔记本上塞满了各种文件,硬盘又不大,才 500G ,平时只能靠到处删文件才能维持日常的使用。。。。
当时装 Debian 的时候给交换分区划了 8G 空间,之后又加插了 8G 的内存,根本用不着,看着日常几百兆剩余的家目录,我开始觊觎交换空间了。。。。
相比于使用一个磁盘分区作为交换空间,使用交换文件可以更方便地随时调整大小或者移除。当磁盘空间有限(例如常规大小的SSD)时,使用交换文件更加理想。From Archlinux Wiki
首先建一个交换文件,一般使用 root 建在根目录,命名为swapfile:

# fallocate -l 512M /swapfile

fallocate 指令可以让您快速建立一个大文件,大小可以在 -l 后指定,当然也可以用 dd 指令,但讲道理没必要。
交换文件建好后需要修改权限,出于安全考虑,只要给使用者读写权限就可以了:

# chmod 600 /swapfile

之后格式化:

# mkswap /swapfile

最后启用交换文件:

# swapon /swapfile

当然,我的笔记本是要频繁开关机的,最好启动后自动启用交换文件,所以要在 /etc/fstab 中添加魔法语句

# vim /etc/fstab

添加内容:

/swapfile none swap defaults 0 0

如果要删除交换文件,需要先停用:

# swapoff -a

然后用世界闻名的 rm 命令:

# rm -rf /swapfile

不要忘了 /etc/fstab 上写的魔法语句。

看起来很麻烦,有没有自动化的工具?
有一种叫 systemd-swap 的神奇 package,你只要安装它,在 /etc/systemd/swap.conf 中启用 swapfu_enabled=1,然后 enable 一下:

# systemctl enable --now systemd-swap

然后它就开始干活了。。。
我也没用过,详细可见项目的 README.md

我电脑内存很大,要交换空间干啥?事实上,交换空间存在与否会影响系统的部分决策,如果你需要让你的计算机休眠就必须拥有交换空间,而且,内存爆炸的情况下交换空间说不定可以保命。。。。

上面有提休眠,如果使用交换文件休眠,要恢复系统得向内核添加参数 resume_offset=Swap_File_Offset
按我配置的例子:

# filefrag -v /swapfile
Filesystem type is: ef53
File size of /swapfile is 536870912 (131072 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 0: 313344.. 313344: 1:
1: 1.. 30719: 313345.. 344063: 30719: unwritten
2: 30720.. 61439: 344064.. 374783: 30720: unwritten
3: 61440.. 92159: 374784.. 405503: 30720: unwritten
4: 92160.. 122879: 405504.. 436223: 30720: unwritten
5: 122880.. 131071: 436224.. 444415: 8192: last,unwritten,eof
/swapfile: 1 extent found

得到 Swap_File_Offset 值:313344,对,就是第一行 physical_offset 底下那个值。
之后在 bootloader 中增加resume内核参数(我使用了 grub2):

# vim /etc/default/grub

GRUB_CMDLINE_LINUX_DEFAULT 这一条的引号里继续添加 resume=/dev/sda几 (sda几得看交换文件放在哪)和 resume_offset=313344,用空格隔开,看起来可能是这样:

GRUB_CMDLINE_LINUX_DEFAULT="quiet resume=/dev/sda1 resume_offset=313344"

然后更新 grub 配置:

# grub-mkconfig -o /boot/grub/grub.cfg

然后配置 initramfs的resume钩子:

# vim /etc/mkinitcpio.conf

HOOKS 行的 udev autodetect 之间添加 resume,(如果使用 lvm 分区,需要将 resume 放在 lvm 后面)完成后看起来大概是这样:

HOOKS="base udev resume autodetect modconf block filesystems keyboard fsck"

最后重新生成 initramfs 镜像:

mkinitcpio -p linux

重启,然后就可以使用了^_^
PS: systemd-swap 好像不能用于休眠

初版于 2017年11月19日 19:15