「電源管理/サスペンドとハイバネート」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(わかりにくい表現を変更)
76行目: 76行目:
 
==== スワップファイルにハイバネーション ====
 
==== スワップファイルにハイバネーション ====
   
{{Warning|[[Btrfs#スワップファイル|Btrfs]] はスワップファイルをサポートしていません。この警告に従わない場合、ファイルシステムが破損するおそれがあります。ループデバイスを経由してマウントしているときに Btrfs でスワップファイルを使うと、スワップパフォーマンスが著しく低下してしまいます。}}
+
{{Warning|バージョン5.0以前のLinuxカーネルでは [[Btrfs#スワップファイル|Btrfs]] はスワップファイルをサポートしていません。この警告に従わない場合、ファイルシステムが破損するおそれがあります。ループデバイスを経由してマウントしているときに Btrfs でスワップファイルを使うと、スワップパフォーマンスが著しく低下してしまいます。}}
   
 
スワップパーティションの代わりにスワップファイルを使うには追加のカーネルパラメータ {{ic|1=resume_offset=''swap_file_offset''}} が必要です。
 
スワップパーティションの代わりにスワップファイルを使うには追加のカーネルパラメータ {{ic|1=resume_offset=''swap_file_offset''}} が必要です。

2022年3月16日 (水) 23:14時点における版

関連記事

現在サスペンドには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 より小さかったとしても、ハイバネートが成功する可能性は高いと思われます。カーネルドキュメント によると:

/sys/power/image_size は suspend-to-disk によって作成されるイメージのサイズを制御します。イメージサイズの上限として使われる負ではない整数 (バイト) を示す文字列で書くことが出来ます。suspend-to-disk はイメージサイズがその数字を超えないように出来る限りのことをします。ただし、それが無理だということがわかったら、とにかく出来る限り小さいイメージを使ってサスペンドを試みます。特に、このファイルに "0" と書かれていた場合、サスペンドのイメージは目一杯小さくなります。このファイルを読むと現在のイメージのサイズ制限が表示され、デフォルトでは利用可能な RAM の2/5に設定されています。

(スワップパーティションを小さくして) /sys/power/image_size の値を減らしてサスペンドのイメージを出来る限り小さくすることも、値を増やしてハイバネーションを高速化することも可能です。

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

カーネルパラメータ resume=swap_partition を使う必要があります。swap_partition にはカーネルが割り当てたスワップパーティションの名前か、スワップパーティションの UUID を使うことができます。例:

  • resume=/dev/sda1
  • resume=UUID=4209c845-f495-4c43-8a03-5363dd433153
  • resume=/dev/mapper/archVolumeGroup-archLogicVolume -- LVM を使う場合の例

resume パラメータで使用する命名法は基本的に root パラメータで使用する命名法と同じにしてください。

設定は使用しているブートローダーによって異なります。詳しくはカーネルパラメータを参照してください。

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

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

スワップパーティションの代わりにスワップファイルを使うには追加のカーネルパラメータ resume_offset=swap_file_offset が必要です。

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_file_offset の値は swap-offset swap_file でも取得することができます。swap-offset バイナリは uswsusp-gitAUR パッケージに含まれています。

ノート:
  • カーネルパラメータ resume にはスワップファイル自体ではなく、スワップファイルが含まれているパーティションのデバイスを指定する必要があることに注意してください。カーネルパラメータ resume_offset は resume デバイス上に存在するスワップファイルの開始位置を示しています。カーネルパラメータを有効化するために、ハイバネーションをする前に再起動が必要です。
  • uswsusp を使う場合、resume device キーと resume offset キーを使って /etc/suspend.conf に上記2つのパラメータを記述してください。この場合再起動は必要ありません。
ヒント: スワップファイルを作成する目的が、仮想メモリの拡張ではなくハイバネートがしたいだけの場合、スワップファイルの Swappiness を減らすとよいでしょう。

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

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

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

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 されたボリュームへの休止状態は可能ですが、ボリュームが完全に割り当てられていることを確認する必要があります。 そうしないと、再開に失敗します。

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 modconf block resume filesystems keyboard 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) に追加されています [3]

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

現在の設定を確認:

$ 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.