本主旨在记录Linux的Btrfs文件系统下开启休眠的过程,及使用systemd-boot替代grub启动时的设置。
Introduction 计算机有S0,S1,S2,S3,S4,S5状态。S4是指休眠(Hibernation),S5即关机(Shutdown)。 S0: 正常的工作状态,所有设备全开; S1: Standby,除了通过CPU时钟控制器将CPU关闭之外,其他的部件仍然正常工作; S2: Standby,CPU处于停止运作状态,总线时钟也被关闭,但其余的设备仍然运转,和 S1 几乎一样; S3: Suspend to RAM,系统运行中的所有资料保存不动,进入假关机,除内存需电源供电外,其它设备全部停止供电; S4: Suspend to Disk,把内存中的资料完整的保存在硬盘中,重开机时直接从硬盘完整的读到RAM。使用这种模式,硬盘需留出一完整的连续的空间; S5: Shutdown。 综上,待机下电池一旦耗尽,内存的内容将丢失,而休眠可以在断电情况下保存运行状态,即将主存内容保存在硬盘中的某个区域,然后断电。Windows下的快速启动遇刺类似。 由于正在使用Btrfs,根据Archwiki所述开启Linux休眠。在这里选择休眠到文件(Swap To File);
Create Subvolume and Swap File
我有两块SSD,都使用了btrfs,所以在其中一块专门存储数据的SSD上创建子卷及交换文件。因为所谓存储盘的原因,我开启了COW,而休眠文件需要关闭COW,且由于Archwiki 1 提到的原因,nodatacow挂载选项可能没有效果,所以考虑直接对休眠文件运行chattr +C
来控制
within a single file system, it is not possible to mount some subvolumes with nodatacow and others with datacow. The mount option of the first mounted subvolume applies to any other subvolumes.
1 2 3 [root@Linux]# export fs_uuid=$(findmnt /Misc -o UUID -n) && echo $fs_uuid [root@Linux]# btrfs subvolume create /Misc/@swap [root@Linux]# mount -m -U $fs_uuid -o subvol=@swap,nodatacow /swap
创建交换文件并且设置权限
1 2 3 4 5 6 [root@Linux]# touch /swap/swapfile[root@Linux]# chattr +C /swap/swapfile [root@Linux]# export swp_size=$(echo "$(grep "MemTotal" /proc/meminfo | tr -d "[:blank:],[:alpha:],:" ) * 1 / 1000" | bc ) && echo $swp_size [root@Linux]# dd if =/dev/zero of=/swap/swapfile bs=1M count=$swp_size status=progress[root@Linux]# chmod 0600 /swap/swapfile[root@Linux]# mkswap /swap/swapfile
在/etc/fstab文件中添加相应自动挂载条目
1 2 3 4 5 6 7 [root@Linux]# umount /swap [root@Linux]# echo -e "UUID=$fs_uuid \t/swap\tbtrfs\tsubvol=@swap,nodatacow,noatime,nospace_cache\t0\t0" | sudo tee -a /etc/fstab[root@Linux]# echo -e "/swap/swapfile\tnone\tswap\tdefaults\t0\t0" | sudo tee -a /etc/fstab[root@Linux]# systemctl daemon-reload [root@Linux]# mount /swap [root@Linux]# swapon -a [root@Linux]# swapon -s
Enable Hiberation with grub or systemd-boot
查看btfs下swapfile真实文件地址及Service文件编写
1 2 3 4 5 6 7 [root@Linux]# export swp_uuid=$(findmnt -no UUID -T /swap/swapfile) && echo $swp_uuid [root@Linux]# curl -s "https://raw.githubusercontent.com/osandov/osandov-linux/master/scripts/btrfs_map_physical.c" > bmp.c [root@Linux]# gcc -O2 -o bmp bmp.c [root@Linux]# swp_offset=$(echo "$(sudo ./bmp /swap/swapfile | egrep "^0\s+" | cut -f9) / $(getconf PAGESIZE) " | bc) && echo $swp_offset [root@Linux]# sudo mkdir -pv /etc/systemd/system/{systemd-logind.service.d,systemd-hibernate.service.d} [root@Linux]# echo -e "[Service]\nEnvironment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1" | sudo tee /etc/systemd/system/systemd-logind.service.d/override.conf[root@Linux]# echo -e "[Service]\nEnvironment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1" | sudo tee /etc/systemd/system/systemd-hibernate.service.d/override.conf
修改initramfs生成配置文件及开机启动配置文件
1 2 [root@Linux]# echo -e "HOOKS+=( resume )" | sudo tee -a /etc/mkinitcpio.conf[root@Linux]# mkinitcpio -P
若使用grub则修改/etc/default/grub
配置文件,然后重新生成grub.cfg
:
1 2 [root@Linux]# echo -e "GRUB_CMDLINE_LINUX_DEFAULT+=\" resume=UUID=$swp_uuid resume_offset=$swp_offset \"" | sudo tee -a /etc/default/grub[root@Linux]# grub-mkconfig -o /boot/grub/grub.cfg
若使用systemd-boot 2 则,直接修改启动项配置/boot/loader/entries/xxx.conf
即可:
1 [root@Linux]# echo -e "options resume=UUID=$swp_uuid resume_offset=$swp_offset " | sudo tee -a /boot/loader/entries/arch.conf
then reboot,test withsudo systemctl hibernate
参考