電源管理/サスペンドとハイバネート

提供: ArchWiki
ナビゲーションに移動 検索に移動

関連記事

現在サスペンドには3つの手法が存在します: suspend to RAM (通常はサスペンドとだけ呼ばれます)、suspend to disk (通常はハイバネートと呼ばれます)、そして hybrid suspend (suspend to both とも呼ばれます):

  • Suspend to RAM は RAM を除くマシンのほとんど全てのパーツの電源を切ります。RAM への電源はマシンの状態を保存するために必要です。電力を多く節約できるので、ラップトップでは、バッテリーでコンピュータが稼働していてフタが閉じられた時 (もしくはユーザーが長い間操作しなかった時) は自動的にこのモードに移行するのが得策でしょう。
  • Suspend to disk はマシンの状態をスワップ領域に保存してマシンの電源を完全にオフにします。マシンに電源を入れた時、状態が復元されます。それまでは、電力消費量はゼロです。
  • Suspend to both はマシンの状態をスワップ領域に保存しますが、マシンの電源を切りません。代わりに、通常の suspend to RAM を呼び出します。これによって、バッテリーを使いきっても、システムを RAM から復帰することが可能です。バッテリーが枯渇した時は、システムはディスクから復帰し、RAM からの復帰に比べて時間がかかりますが、システムの状態が失われることはありません。

基本的な機能を提供する低レベルなインターフェイス (バックエンド) が複数存在し、問題のあるハードウェアドライバ・カーネルモジュール (例: ビデオカードの再初期化) を扱う機能を提供する高レベルなインターフェイスもいくつかあります。

低レベルインターフェイス

これらのインターフェイスは直接使うこともできますが、通常は高レベルインターフェイスを使ってサスペンド・ハイバネートを行うとよいでしょう。低レベルなインターフェイスを直接使うと、サスペンドの前や後に行うフック処理を全て実行する高レベルインターフェイスよりもかなり早くサスペンドが可能です。ただしフックはハードウェアクロックの設定や、ワイヤレスの復旧などを正しく処理することができます。

カーネル (swsusp)

直球の方法はカーネル内のソフトウェアサスペンドコード (swsusp) にサスペンド状態に入るよう直接伝えることです。実際の方法と状態はハードウェアサポートのレベルによります。最近のカーネルでは、サスペンドにするために /sys/power/state に適切な文字列を書くことが主な方法になっています。

詳しくは カーネルドキュメント を参照してください。

uswsusp

uswsusp ('Userspace Software Suspend') はカーネルの suspend-to-RAM のラッパーで、サスペンドの前と復帰の後にユーザー空間からグラフィックアダプタの操作を行います。

Uswsusp の記事を参照してください。

高レベルインターフェイス

ノート: これらのパッケージではサスペンド・ハイバネートを行うためのバイナリ・スクリプトを提供します。実際に電源ボタンやメニュークリック、ラップトップのカバーのイベントなどと結びつけるのは他のツールで行うのが通常です。(ラップトップのカバーが閉じられたり、バッテリーが枯渇するなど)特定の電源イベントで自動的にサスペンド・ハイバネートをするには、Acpid の実行について調べて下さい。

systemd

systemd はサスペンド・ハイバネート・ハイブリッドサスペンドを行うためのネイティブのコマンドを提供しています。詳しくは 電源管理#systemd による電源管理 を見て下さい。これは Arch Linux で使われているデフォルトのインターフェースです。

サスペンド・ハイバネートのフックの設定に関する情報は電源管理#スリープフックに載っています。man systemctl, man systemd-sleep, man systemd.special もあわせて参照してください。

ハイバネーション

ハイバネーションを使うには、スワップパーティションかスワップファイルを作成する必要があります。そして resume= カーネルパラメータを使ってスワップを指定してください。カーネルパラメータはブートローダで設定します。initramfs の設定も必要になります。設定によってカーネルは初期ユーザー空間で指定されたスワップからの復帰を試みます。以下ではスワップの作成・カーネルパラメータの設定・initramfs の設定について詳細に説明します。

ノート:

スワップパーティション(ファイル)のサイズについて

スワップパーティションが RAM より小さかったとしても、ハイバネートが成功する可能性は高いと思われます。image_size sysfs(5) 疑似ファイルに関する情報は kernel documentation の "image_size" を見てください。

(スワップパーティションを小さくして) /sys/power/image_size の値を減らしてサスペンドのイメージを出来る限り小さくすることも、値を増やしてハイバネーションを高速化することも可能です。大きな容量の RAM を搭載しているシステムでは、より小さい値にするとハイバネートからの復帰が劇的に速くなることがあります。

image_size の値を再起動後も保持するために systemd#systemd-tmpfiles - 一時ファイル を使うことができます:

/etc/tmpfiles.d/hibernation_image_size.conf
#    Path                   Mode UID  GID  Age Argument
w    /sys/power/image_size  -    -    -    -   0

サスペンドイメージは複数のスワップパーティション/スワップファイルにまたがって保存することができません。イメージのすべての部分が1つのスワップパーティション/スワップファイルに収まらなければなりません。[1]

必要なカーネルパラメータ

カーネルパラメータ resume=swap_device を使う必要があります。永続的なブロックデバイスの命名swap_device に使用することができます。例:

  • resume=/dev/sda1
  • resume=UUID=4209c845-f495-4c43-8a03-5363dd433153
  • resume=/dev/mapper/archVolumeGroup-archLogicVolume -- スワップが LVM 論理ボリュームにある場合

カーネルパラメータは再起動後に有効となります。すぐにハイバネートできるようにするには、lsblk を使ってボリュームのメジャーデバイスナンバーとマイナーデバイスナンバーを手に入れて、/sys/power/resumemajor:minor という形式で書き込んでください。スワップファイルを使用している場合は、追加で /sys/power/resume_offset に resume オフセットを書き込んでください。[2]

例えば、スワップデバイスが 8:3 の場合:

# echo 8:3 > /sys/power/resume

スワップファイルにハイバネートする場合で、スワップファイルがボリューム 8:2 にあり、オフセットが 38912 の場合:

# echo 8:2 > /sys/power/resume
# echo 38912 > /sys/power/resume_offset

スワップファイルにハイバネーション

警告: バージョン5.0以前のLinuxカーネルでは Btrfs はスワップファイルをサポートしていません。この警告に従わない場合、ファイルシステムが破損するおそれがあります。ループデバイスを経由してマウントしているときに Btrfs でスワップファイルを使うと、スワップパフォーマンスが著しく低下してしまいます。

スワップファイル を使用するには resume=swap_device だけでなく、resume_offset=swap_file_offset カーネルパラメータも設定する必要があります。カーネルのドキュメントを見てください。

swap_device はスワップファイルが存在するボリュームで、root パラメータと同じ形式に従います。swap_file_offset の値は filefrag -v swap_file を実行することで取得できます。テーブル形式で出力され、必要な値は physical_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
...

この例では swap_file_offset の値は2つのピリオドが付いている最初の 38912 です。

ヒント:
  • 次のコマンドは swap_device を特定するのに利用できます: findmnt -no UUID -T /swapfile
  • 次のコマンドは swap_file_offset を特定するのに利用できます: filefrag -v /swapfile | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
  • swap_file_offset の値は swap-offset swap_file を実行することによっても得られます。 swap-offset バイナリは uswsusp ツールのセットで提供されています。 もしこの方法を利用するならば、これら2つのパラメータは /etc/suspend.conf 内で resume deviceresume offset というキーで渡されなければなりません。この場合、再起動は必要ありません。
ノート:
  • 暗号化コンテナ (LUKS)、 RAID、 LVM のようなスタックブロックデバイスでは、resume パラメータはスワップファイルのあるファイルシステムを含んでいる、アンロックまたはマップされたデバイスを指していなければなりません。
  • スワップファイルが /home/ に存在する場合、systemd-logind はスワップファイルのサイズを正しく判断することができないため、以下のメッセージによりハイバネートを停止します: Failed to hibernate system via logind: Not enough swap space for hibernation。2つの回避策については systemd issue 15354 をご覧ください。
ヒント: スワップファイルを作成する目的が、仮想メモリの拡張ではなくハイバネートがしたいだけの場合、スワップファイルの Swappiness を減らすとよいでしょう。

Btrfs のスワップファイルへのハイバネーション

スワップファイルへの休止状態は、systemd の最近のバージョン [3] でサポートされています。

resume_offset 番号は、 tool btrfs_map_physical.c を使用して計算できます。 Btrfs では、 filefrag ツールを使用しないでください。 filefrag から取得する 物理的 オフセットは、ディスク上の実際の物理的オフセットではありません。 複数のデバイスをサポートするために、仮想ディスクのアドレス空間があります。 [4]

tool btrfs_map_physical.c をダウンロードするか、 btrfs_map_physical.c という名前のファイルにコピーしてからコンパイルします。

$ gcc -O2 -o btrfs_map_physical btrfs_map_physical.c

そしてそれを実行します。 出力例を以下に示します。

# ./btrfs_map_physical /path/to/swapfile
FILE OFFSET  EXTENT TYPE  LOGICAL SIZE  LOGICAL OFFSET  PHYSICAL SIZE  DEVID  PHYSICAL OFFSET
0            regular      4096          2927632384      268435456      1      4009762816
4096         prealloc     268431360     2927636480      268431360      1      4009766912
268435456    prealloc     268435456     3251634176      268435456      1      4333764608
536870912    prealloc     268435456     3520069632      268435456      1      4602200064
805306368    prealloc     268435456     3788505088      268435456      1      4870635520
1073741824   prealloc     268435456     4056940544      268435456      1      5139070976
1342177280   prealloc     268435456     4325376000      268435456      1      5407506432
1610612736   prealloc     268435456     4593811456      268435456      1      5675941888

このツールによって返される最初の物理オフセットに注意してください。 この例では、 4009762816 を使用します。 getconf PAGESIZE で見つけることができるページサイズにも注意してください。

resume_offset 値を計算するには、物理オフセットをページサイズで割ります。 この例では、 4009762816 / 4096 = 978946 です。

thinly-provisioned LVM ボリュームへのハイバネーション

thinly-provisioned LVM されたボリュームへの休止状態は可能ですが、ボリュームが完全に割り当てられていることを確認する必要があります。そうしないと、再開に失敗します。FS#50703 を見てください。

LVM ボリュームをゼロで埋めるだけで、 LVM ボリュームを完全に割り当てることができます。 例えば:

# dd if=/dev/zero of=/dev/vg0/swap bs=1M status=progress

ボリュームが完全に割り当てられていることを確認するには、次を使用できます:

# lvs
 LV                   VG  Attr       LSize   Pool Origin    Data%  Meta%  Move Log Cpy%Sync Convert
 swap                 vg0 Vwi-aot--- 10.00g  pool           100

完全に割り当てられたボリュームは、100%のデータ使用量であると表示されます。

警告: 休止状態に使用される thinly-provisioned されたスワップボリュームで TRIM を使用しないでください。つまり、 /etc/fstabdiscard を使用しないでください。 swapon-d/--discard オプション。 そうしないと、使用済みスペースの割り当てが解除されます。

initramfs の設定

  • initramfsbase フックを使っている場合 (Arch ではデフォルトで使っています)、/etc/mkinitcpio.confresume フックを追加する必要があります。ラベルあるいは UUID どちらを使用している場合でもスワップパーティションは udev デバイスノードによって参照されるので、resume フックは必ず filesystems の前に追加してください。デフォルトのフック設定に resume フックを追加すると以下のようになります:
HOOKS=(base udev autodetect keyboard modconf block filesystems resume fsck)
変更を適用するために initramfs の再生成を忘れずに行ってください。
ノート: LVM を使っている場合は resume フックを lvm2 の後に追加してください。
  • initramfs で systemd フックを使っている場合は、復帰機構が既に提供されているので、フックを追加する必要はありません。

Intel Rapid Start Technology (IRST)

Intel Rapid Start Technology (IRST) が有効の場合、 deep sleep からの再開には "S3から再開するよりも数秒長くなりますが、休止状態から再開するよりもはるかに高速です"。

Intel ベースのシステムの多くは、 IRST のファームウェアをサポートしていますが、 (HDDではなく) SSD 上に特別なパーティションを必要とします。 Windows の OEM 展開では、Arch Linux インストールプロセス中に (SSD 全体を消去して再パーティションするのではなく) 保持できる IRST パーティションがすでに存在している場合があります。システムの RAM と同じサイズの未フォーマットパーティションとして表示されます。

警告: Intel Rapid Start パーティションは暗号化されていません。

しかし、ドライブ全体を消去してパーティションを切り直すつもりなら (あるいはすでにそうしてしまっているなら) IRST パーティションも再作成しなければなりません。これを行うには、システムの RAM と同じサイズの空のパーティションを作成し、そのパーティションの種類が GPT パーティションの場合は GUID D3BFE2DE-3DAF-11DF-BA40-E3A556D89593 に、 MBR パーティションの場合は ID 0 x 84 に設定します。また、システムのファームウェア設定で IRST のサポートを有効にする必要がある場合もあります。

ヒント: IRST が開始されるまでの時間 (サスペンド後) は、システムのファームウェア設定で調整できます。

IRST 休止状態プロセスの時間 ("RAMの内容全体を特殊なパーティションに" コピー) は、システムの RAM サイズと SSD 速度によって異なり、20~60秒かかります。システムによっては、プロセスの完了を LED インジケータで示す場合があります (点滅が停止した場合など)

トラブルシューティング

ACPI_OS_NAME

DSDT table を動作するように設定することができます。DSDT の記事を参照してください。

サスペンド/ハイバネートが動作しない、あるいはたまに動作しなくなる

サスペンドやハイバネートをした場合、あるいは復帰した場合に画面が表示されなくなるという報告が多数存在します。ノートパソコンとデスクトップの両方で問題は確認されています。正式な解決方法ではありませんが、古いカーネル、特に LTS カーネルに切り替えることで問題は解決することがあります。

initramfs からのデバイスの初期化によって画面が表示されなくなっていることもあります。Mkinitcpio#MODULES に追加したモジュールを削除して initramfs を再生成することで問題が解決するかもしれません。特にグラフィックドライバのモジュールは問題を起こしがちです。復帰するまえにデバイスが初期化されると矛盾状態になってシステムがハイバネートから復帰できなくなります。サスペンドからの復帰の場合は関係ありません。サスペンドやハイバネートの問題をデバッグする際のベストプラクティスが こちらの記事 に記載されています。

Wake-on-LAN

Wake-on-LAN が有効になっている場合、コンピュータがハイバネート状態になっていてもネットワークインターフェイスカードによって電力が消費されます。

サスペンドからすぐに復帰する

LynxPoint や LynxPoint-LP チップセットが搭載された Intel Haswell の場合、サスペンドからすぐに復帰してしまうと報告されています。BIOS の ACPI 実装に問題があり起動時に xhci_hcd モジュールによって ACPI イベントが解釈されてしまうのが原因です。解決策としてカーネルによってケースバイケースで問題のあるシステムがブラックリスト (XHCI_SPURIOUS_WAKEUP) に追加されています [5]

サスペンド中に USB デバイスを接続したときなどに ACPI の復帰トリガーが有効になって復帰してしまいます。ブラックリストに追加されるまで一時的な応急処置としては復帰トリガーを無効化する方法があります。以下の設定で USB による復帰を無効化することができます [6]

現在の設定を確認:

$ cat /proc/acpi/wakeup
Device  S-state   Status   Sysfs node
...
EHC1      S3    *enabled  pci:0000:00:1d.0
EHC2      S3    *enabled  pci:0000:00:1a.0
XHC       S3    *enabled  pci:0000:00:14.0
...

問題のデバイスは EHC1, EHC1, XHC (USB 3.0) です。状態を変更するには root でデバイス名をファイルに echo してください:

# echo EHC1 > /proc/acpi/wakeup
# echo EHC2 > /proc/acpi/wakeup
# echo XHC > /proc/acpi/wakeup

上記のコマンドでサスペンドが再度機能するようになります。ただし、設定は一時的なものなので再起動するたびに設定し直す必要があります。自動化したい場合は systemd#ユニットファイルを見てください。詳しくは BBS スレッド を参照。

System does not power off when hibernating

​ When you hibernate your system, the system should power off (after saving the state on the disk). Sometimes, you might see the power LED is still glowing. If that happens, it might be instructive to set the HibernateMode to shutdown in sleep.conf.d(5): ​

/etc/systemd/sleep.conf.d/hibernatemode.conf
[Sleep]
HibernateMode=shutdown

​ With the above configuration, if everything else is set up correctly, on invocation of a systemctl hibernate the machine will shutdown saving state to disk as it does so.