4月から個人 PC を MacBook Air から Linux マシンに変えました。[2021-05-06-1]

スライド P41 に書いたとおり、たまにスリープから復帰しなくてつらいです。仕方がないので「スリープしない設定にする。常にAC電源ON🤗」という運用でカバー()をしていました。😭

いつまでも続けるわけにもいかないので、今回重い腰を上げてハイバネート出来るようにしました。

Linux (Xfce4) のスリープ方式

私が使っているウィンドウマネージャーは Xfce4 です。電源管理の設定等で出てくるスリープ関連の用語と、自分なりの理解は以下のとおりです。情報源は Wikipedia です。😆

  • サスペンド
    • メモリ以外の給電停止した状態。ACPI では S3 に相当する
  • ハイバネート
    • メモリの内容をストレージに移し電源断。ACPI では S4 に相当する
  • ハイブリッドスリープ
    • サスペンドとハイバネートの中間だと思われるが、試したらすぐハイバネートしただけだった…

macOS (Big Sur) のスリープ方式

macOS ではサスペンドやハイバネートの使い分けは不要で、意識するのは「スリープ」のみです。以下のような「セーフスリープ 」という機構を備えているそうです。

  • スリープ状態になると、メモリの内容を保持したままストレージにも保存する
  • スリープ中にバッテリーが切れていなければ、復帰時にメモリの内容を使う
  • スリープ中にバッテリーが切れていたら、復帰時にストレージの内容を使う

奨励はされていませんが、pmset コマンドでスリープ方式を「セーフスリープ」から「スリープ」または「ディープスリープ」に変更は出来るようです。

「スリープ」は ACPI の S3 に相当し、「ディープスリープ」は S4 に相当するようなので、Xfce4 の「ハイブリッドスリープ」は「セーフスリープ」が本来の振る舞いなのかも。

※ 状態としての「スリープ」と、その種類としての「スリープ」(と「セーフスリープ」「ディープスリープ」)があるので、文章がややこしいです。

Linux と macOS の振る舞いの違い

macOS の素晴らしい点に、ユーザーにスリープをほぼ意識させない設計があると思います。

サスペンドやハイバネートのような用語が現れないこともさることながら、MacBook なら蓋を開けばログイン画面が表示されるだけです。多少復帰がもたつくことはあるのはご愛嬌。

Linux はサスペンドは同じとしても、ハイバネートは OS の起動から始まるので、「あれ?バッテリー切れてた?」と一瞬不安になります。Windows も同じという理解です。

どの OS もバックグラウンドの処理は同じだと思います。macOS はユーザーへの見せ方がきれいですね。

Manjaro でのハイバネート設定方法

サスペンドとハイバネート - ArchWiki 」に従いました。以下の流れです。

  1. スワップファイルを作る
  2. 関連するカーネルパラメータを GRUB(ブートローダー)に追加する
  3. 関連するフックを initramfs に追加する

1. スワップファイルを作る

今回は /swapfile という 18GB のスワップファイルを作りました。

$ sudo fallocate -l 18G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile

この VivoBook のメモリは 16GB です。RedHat の記事 に従い、スワップファイルのサイズは 18GB にしました。

無事作られました。

$ swapon -show
Filename   Type  Size      Used  Priority
/swapfile  file  18874364  0     -2

永続化するために /etc/fstab に以下を追記しました。

/swapfile none swap defaults 0 0

ちなみに、今回のような任意サイズのファイルは dd でも作れます。ただ、dd は実際にファイル書き込みが発生するため、可能なら fallocate を使うほうが無駄がなくて良いと思います。

参考記事: Linuxでサイズ指定してダミーファイルを作成する方法 - conf t

2. 関連するカーネルパラメータを GRUB(ブートローダー)に追加する

/etc/default/grub を以下のように変更しました。/swapfile が、どのデバイスの、どの位置(オフセット)に存在するかを教えています。

--- /tmp/grub.orig	2021-08-25 01:12:57.415049508 +0900
+++ /etc/default/grub	2021-08-23 23:42:08.875333968 +0900
@@ -2,7 +2,7 @@
 GRUB_TIMEOUT=5
 GRUB_TIMEOUT_STYLE=hidden
 GRUB_DISTRIBUTOR="Manjaro"
-GRUB_CMDLINE_LINUX_DEFAULT="quiet apparmor=1 security=apparmor udev.log_priority=3"
+GRUB_CMDLINE_LINUX_DEFAULT="quiet apparmor=1 security=apparmor udev.log_priority=3 resume=UUID=52d772c6-e49d-4be0-9963-c9aae2a9e4f9 resume_offset=52037632"
 GRUB_CMDLINE_LINUX=""

 # If you want to enable the save default function, uncomment the following

GRUB_CMDLINE_LINUX がユーザー用の変数かと思い、初めはこれを使ってしまいましたが、リカバリモード用でした(GNU GRUB Manual 2.06: Simple configuration )。

“resume=UUID=52d772c6-e49d-4be0-9963-c9aae2a9e4f9” で、/swapfile が置いてあるデバイスを教えています。

雑に調べると /dev/nvme0n1p5 です。/swapfile なので当たり前ですが、"/" がマウントポイントです。

$ df /swapfile
Filesystem     1K-blocks     Used Available Use% Mounted on
/dev/nvme0n1p5 527306168 62862840 437583404  13% /

“resume=/dev/nvme0n1p5” でも問題はないとは思いますが、外付けストレージの追加等で名前が変わるリスクはゼロではないため、UUID による永続的な命名方法を使いました。

各デバイスの UUID 確認方法は簡単です(永続的なブロックデバイスの命名 - ArchWiki )。

$ ls -alF /dev/disk/by-uuid
total 0
drwxr-xr-x 2 root root 100  8月 24 00:14 ./
drwxr-xr-x 8 root root 160  8月 24 00:14 ../
lrwxrwxrwx 1 root root  15  8月 24 00:14 2E80-83B2 -> ../../nvme0n1p1
lrwxrwxrwx 1 root root  15  8月 24 00:14 52d772c6-e49d-4be0-9963-c9aae2a9e4f9 -> ../../nvme0n1p5
lrwxrwxrwx 1 root root  15  8月 24 00:14 DA82730D8272ECFF -> ../../nvme0n1p4

“resume_offset=52037632” で、/swapfile が /dev/nvme0n1p5 の先頭からどの位置(オフセット)に存在するかを教えています。

filefrag というコマンドで分かるようです。

$ sudo filefrag -v /swapfile | head -n 5
Filesystem type is: ef53
File size of /swapfile is 19327352832 (4718592 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       0:   52037632..  52037632:      1:
   1:        1..    2047:   52037633..  52039679:   2047:             unwritten

ext4 はフラグメンテーションが起きづらいそうだけど、e4defrag で手動デフラグしたらオフセットは変わり得るのでは?と思いました。ちょっと怖いな。どうなんでしょう?

/etc/default/grub を変更したら /boot/grub/grub.cfg を再作成します。

$ sudo grub-mkconfig -o /boot/grub/grub.cfg

3. 関連するフックを initramfs に追加する

/etc/mkinitcpio.conf を以下のように変更しました。カーネル起動時に resume というモジュールがロードされるのかな。filesystems の前に追加するのがとても重要だそうです。

--- /tmp/mkinitcpio.conf.orig	2021-08-25 01:40:50.793227026 +0900
+++ /etc/mkinitcpio.conf	2021-08-23 23:07:04.396638336 +0900
@@ -49,7 +49,7 @@
 #
 ##   NOTE: If you have /usr on a separate partition, you MUST include the
 #    usr, fsck and shutdown hooks.
-HOOKS="base udev autodetect modconf block keyboard keymap filesystems fsck"
+HOOKS="base udev autodetect modconf block keyboard keymap resume filesystems fsck"

 # COMPRESSION
 # Use this to compress the initramfs image. By default, gzip compression

/etc/mkinitcpio.conf を変更したら /boot/initramfs-*.img を再作成します。

$ sudo mkinitcpio -p linux510

linux510 は /etc/mkinitcpio.d/ 以下のファイルと対応していました。今回は /etc/mkinitcpio.d/linux510.preset しかなかったので、linux510 になりました。

ちなみに mkinitcpio を引数なしで実行すると、dry run モードによる確認が出来ます。

$ sudo mkinitcpio
==> Starting dry run: 5.10.59-1-MANJARO
  -> Running build hook: [base]
  -> Running build hook: [udev]
  -> Running build hook: [autodetect]
  -> Running build hook: [modconf]
  -> Running build hook: [block]
  -> Running build hook: [keyboard]
  -> Running build hook: [keymap]
  -> Running build hook: [resume]
  -> Running build hook: [filesystems]
  -> Running build hook: [fsck]
==> Generating module dependencies
==> Dry run complete, use -g IMAGE to generate a real image

注意点

GRUB や Linux カーネルが更新されたら、2 や 3 の再設定が必要みたいです。面倒なので私は mitamae でゆるふわ構成管理しています。

まとめ

ハイバネート出来た時は、思わずおぉー!と声が出ました。他の OS では当たり前すぎるハイバネートですが、自分で設定すると感慨深いものがあります。

これで VivoBook から気軽に AC 電源コードを抜けるようになりました。なんと当たり前な…。今までは気がつくと電源が落ちていたので、AC 電源コードも気も抜けませんでした。😭

サスペンドは復帰時に画面が表示されず、電源ボタンを長押しするしかなくなることがあるので、まだ使えていません。

前述の「サスペンドとハイバネート - ArchWiki 」によると、この現象は多数報告されているそうです。そして、そのデバッグのベストプラクティスがこの記事 とのこと。

長いので気が向いたら調べます。たぶん、Linux カーネルと ATI のドライバの相性()が悪いのだと思います。

他の参考記事

🔗 Arch Linux 快適デスクトップ環境の構築 2019 - Qiita

🔗 Linux におけるラップトップマシン向け電力管理スイートの紹介(Pm-utils, Laptop-mode-tools, Powertop, TLP) – 怠惰の形而上学
初めからインストールされていた TLP があればサスペンド(スリープ)は問題なく管理されているそう。Laptop-mode-tools はもう古いそう。なのにサスペンドだけだと数時間しかバッテリーがもたないのは、推して知るべし…。