Arch Linux Hibernates¶
在 MacBook Pro上运行Arch Linux 采用的是双操作系统,由于工作原因,需要经常在macOS和Linux之间切换,如果每次重新登陆到Linux操作系统,都要重头开始准备工作环境会非常繁琐(例如打开同样的编辑器和编辑文件,浏览器以及终端)。采用 Hibernages 可以将运行状态存储到磁盘中,这样下次切换到Linux就可以立即恢复到离开时的状态,提高了工作效率。
备注
我在 Ubuntu Hibernate休眠 实践中也有一些经验可以参考。
电源管理¶
Linux支持3中不同的挂起系统模式:
suspend to RAM(也称为suspend): 切断主机大多数部件的电源,但保持RAM电力,这样RAM可以存储主机的状态。由于维持内存的电力消耗很小,所以suspend可以让笔记本电池较长时间供电,并且恢复运行非常迅速。
suspend to disk(也称为hibernate): 通过swap磁盘来保存主机状态,这样就可以不需要电源,完全不消耗电池的电能。缺点是恢复速度比suspend慢,但是可以切换到其他操作系统(例如双启动的macOS)而不会丢失原先的运行状态。
suspend to both(也称为hybrid suspend): 同时将主机状态保存在内存和磁盘swap上,但不断开电能供应。如果电池够用,则直接从RAM恢复系统(速度最快),如果电池电能耗尽,则从磁盘恢复主机状态(速度较慢)。虽然后者比从内存恢复要慢很多,但是在电池电能耗尽情况下依然能够保证主机状态不丢失。
底层接口¶
备注
虽然可以直接使用底层接口实现suspend/hibernate,并且速度较快,但是高层接口可以实现pre-和post-suspend hooks,例如设置硬件时钟,恢复无线网络等。
内核级接口(swsusp)¶
在内核的 /sys/power/state
接口写入相应字符串可以触发suspend。在内核文档中 states.txt 有详细说明。
用户级软件设置(uswsusp)¶
uswsusp(“Userspace Software Suspend”)是包装了内核suspend-to-RAM机制,提供在suspsend和resume时候执行一些图形卡配置。
高层接口¶
systemd¶
systemd原生提供了suspend, hibernate 和 hybrid 支持,这也是Arch Linux使用的默认接口。
hibernation¶
要使用hibernate,需要创建swap磁盘,并且在内核启动参数 resume=
中指定内核使用swap,也就是需要配置 initramfs 来告诉内核从用户空间指定的swap恢复。
对于swap分区小于RAM,依然能够实现hibernate:
/sys/power/image_size
控制了 suspend-to-disk
机制创建的镜像大小,这个值是一个非负的整数,默认设置为内存的 2/5 。
可以调整 /sys/power/image_size
大小,可以尽可能缩小这个swap大小,也可以增加这个swap大小来加速hibernate处理速度。注意,suspend镜像不能跨多个swap分区或者多个swap文件,必须完全存储在一个swap分区或者一个swap文件。
需要的内核参数¶
需要使用内核参数 resume=swap_device
,这里的 swap_device
是持久化块设备命名,例如:
resume=UUID=4209c845-f495-4c43-8a03-5363dd433153
resume="PARTLABEL=Swap partition"
resume=/dev/archVolumeGroup/archLogicalVolume (如果是LVM逻辑卷)
Hibernation到swap文件¶
备注
内核5.0之前不支持Btrfs文件系统的swap文件,如果在Btrfs文件系统中使用swap文件存储hibernetes会导致文件系统损坏。虽然能够在Btrfs中将swap文件挂载成一个loop设备,但是这样会显著降低swap性能。
使用swap文件爱你需要传递给内核参数 resume_offset=swap_file_offset
。
备注
resume
参数必须指向 swap文件所在的卷。对于堆叠类型的块设备,例如加密容器,或者RAID,或者LVM,这意味着 resume
必须指向包含swap文件的文件系统的 unlocked
或者 mapped
设备。
通过 filefreg -v swap_file
可以获得 swap_file_offset
值,输出内容的第一行中 phyiscal_offset
列值就是需要提供的定位值:
filefrag -v /swapfile
输出内容:
Filesystem type is: ef53
File size of /swapfile is 4294967296 (1048576 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 0: 38912.. 38912: 1:
1: 1.. 22527: 38913.. 61439: 22527: unwritten
2: 22528.. 53247: 899072.. 929791: 30720: 61440: unwritten
上述输出中第一行的 physical_offset
列,即 38912
就是我们查询得到的偏移值。
备注
如果安装了 uswsusp
工具包,则提供了一个 swap-offset
命令可以直接输出swap问价的偏移值:
swap-offset swap_file
Hibernate设置实践¶
获取swap文件应该设置的大小:
/sys/power/image_size
例如,输出值是 6672080896
则对应大约 6.4GB
创建swap文件:
dd if=/dev/zero of=/swap bs=64MiB count=100
创建swap:
mkswap /swap swapon /swap
配置
/etc/fstab
添加swap配置:/swap none swap defaults 0 0
获取磁盘分区uuid:
blkid /dev/sda3
输出显示:
/dev/sda3: UUID="e38d80cc-4044-4d34-b730-1f0c874ad765" TYPE="ext4" PARTLABEL="arch_linux" PARTUUID="c31f68cd-97f7-4471-93c7-adb62b22a17b"
获取
/swap
文件偏移量:filefrag -v /swap
输出:
Filesystem type is: ef53
File size of /swap is 6710886400 (1638400 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 32767: 7798784.. 7831551: 32768:
...
则偏移量是: 7798784
需要向内核传递参数:
resume=UUID=e38d80cc-4044-4d34-b730-1f0c874ad765 swap_file_offset=7798784
备注
我在MacBook Pro上使用的EFI设置启动是采用 efibootmgr
,请参考 MacBook Pro上运行Arch Linux ,所以,这里需要通过 efibootmgr
传递内核参数。
将原先设置efibootmgr命令:
efibootmgr --disk /dev/sda --part 1 --create --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=PARTUUID=c31f68cd-97f7-4471-93c7-adb62b22a17b rw initrd=\initramfs-linux.img' --verbose
添加上hibernate参数如下:
efibootmgr --disk /dev/sda --part 1 --create --label "Arch Linux" --loader /vmlinuz-linux --unicode 'root=PARTUUID=c31f68cd-97f7-4471-93c7-adb62b22a17b rw initrd=\initramfs-linux.img resume=UUID=e38d80cc-4044-4d34-b730-1f0c874ad765 swap_file_offset=7798784' --verbose
重启操作系统
重启操作系统后,再次登陆到 xfce 图形界面,此时用户
Log Out
菜单选项中就会增加Hibernate
和Hybrid Sleep
选项。并且cat /proc/cmdline
可以看到内核参数:root=PARTUUID=c31f68cd-97f7-4471-93c7-adb62b22a17b rw initrd=\initramfs-linux.img resume=UUID=e38d80cc-4044-4d34-b730-1f0c874ad765 swap_file_offset=7798784
备注
不过,我此时使用 Hibernate
功能发现操作系统是直接关机了,并没有成功恢复到
参考 Arch Linux社区文档 - MacBookPro11,x#Kernel parameters 提示需要向内核传递参数 acpi_osi=Darwin
才能使 suspension/hibernation
工作正常。
所以MacBook Pro完整的内核启动配置,请参考 MacBook Pro上运行Arch Linux
但是,我发现并没有实现hibernate存储到磁盘的操作,每次执行 systemctl hibernate
实际是直接关机。
按照内核文档:
The states are represented by strings that can be read or written to the
/sys/power/state file. Those strings may be "mem", "standby", "freeze" and
"disk", where the last three always represent Power-On Suspend (if supported),
Suspend-To-Idle and hibernation (Suspend-To-Disk), respectively.
通过直接 echo disk > /sys/power/state
应该能够直接 suspend to disk ,但是我发现在字符终端显示设备不能写入? why
…