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

提供: ArchWiki
ナビゲーションに移動 検索に移動
(同期)
 
(2人の利用者による、間の33版が非表示)
1行目: 1行目:
 
[[Category:電源管理]]
 
[[Category:電源管理]]
  +
[[de:Bereitschaft und Ruhezustand]]
 
[[en:Power management/Suspend and hibernate]]
 
[[en:Power management/Suspend and hibernate]]
  +
[[es:Power management (Español)/Suspend and hibernate]]
  +
[[pt:Power management (Português)/Suspend and hibernate]]
  +
[[ru:Power management (Русский)/Suspend and hibernate]]
  +
[[zh-hans:Power management/Suspend and hibernate]]
 
{{Related articles start}}
 
{{Related articles start}}
{{Related|Uswsusp}}
 
{{Related|TuxOnIce}}
 
 
{{Related|systemd}}
 
{{Related|systemd}}
{{Related|pm-utils}}
 
{{Related|hibernate-script}}
 
 
{{Related|電源管理}}
 
{{Related|電源管理}}
  +
{{Related|電源管理/復帰トリガー}}
  +
{{Related|スワップ}}
 
{{Related articles end}}
 
{{Related articles end}}
現在サスペンドには3つの手法が存在します: '''suspend to RAM''' (通常は'''サスペンド'''とだけ呼ばれます)、'''suspend to disk''' (通常は'''ハイバネート'''と呼ばれます)、そして '''hybrid suspend''' ('''suspend to both''' とも呼ばれます):
 
   
  +
サスペンドの[https://docs.kernel.org/admin-guide/pm/sleep-states.html 複数の方法]を利用できます。とりわけ:
* '''Suspend to RAM''' は RAM を除くマシンのほとんど全てのパーツの電源を切ります。RAM への電源はマシンの状態を保存するために必要です。電力を多く節約できるので、ラップトップでは、バッテリーでコンピュータが稼働していてフタが閉じられた時 (もしくはユーザーが長い間操作しなかった時) は自動的にこのモードに移行するのが得策でしょう。
 
   
  +
; Suspend to idle: Intel は [https://www.intel.com/content/www/us/en/docs/vtune-profiler/user-guide/2023-0/s0ix-states.html S0ix] と呼んでおり、Microsoft は [https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/modern-standby Modern Standby] (以前は "Connected Standby") と呼んでいます。Linux カーネルでは [https://docs.kernel.org/admin-guide/pm/sleep-states.html#suspend-to-idle S2Idle] と呼ばれています。サポートされているシステムにおいて '''S3''' [[Wikipedia:ACPI#Global states|スリープ状態]]の代わりに使用されるように設計されており、同等の節電機能を提供しますが、復帰に掛かる時間が大幅に短縮されます。{{Tip|[https://www.dell.com/support/kbdoc/en-us/000143524/the-battery-drains-quicker-than-expected-on-a-dell-notebook-with-modern-standby-mode-enabled Windows] や [https://support.apple.com/guide/mac-help/mh40773/mac macOS] はネットワーク活動のためにこの状態のデバイスの復帰をサポートしているので、これらの OS においてこの状態はバッテリーの消耗問題の影響を受けます。一方、Linux のソフトウェアエコシステムは現在この機能を使用しないため、影響を受けないはずです。}}
* '''Suspend to disk''' はマシンの状態を[[スワップ|スワップ領域]]に保存してマシンの電源を完全にオフにします。マシンに電源を入れた時、状態が復元されます。それまでは、電力消費量はゼロです。
 
  +
; Suspend to RAM (サスペンド、スリープとも呼ばれます): ACPI で '''S3''' スリープ状態として定義されています。RAM を除くマシンのほとんど全てのパーツの電源を切ります。RAM への電源はマシンの状態を保存するために必要です。電力を多く節約できるので、ラップトップでは、バッテリーでコンピュータが稼働していてフタが閉じられた時 (もしくはユーザーが長い間操作しなかった時) は自動的にこのモードに移行するのが得策でしょう。
  +
; Suspend to disk (ハイバネートとも呼ばれます): ACPI で '''S4''' スリープ状態として定義されています。マシンの状態を[[スワップ|スワップ領域]]に保存してマシンの電源を完全にオフにします。マシンに電源を入れた時、状態が復元されます。それまでは、電力消費量は[[Wikipedia:ja:待機電力|ゼロ]]です。
  +
; Hybrid suspend (ハイブリットスリープとも呼ばれます): サスペンドとハイバネートのハイブリッドです。'''Suspend to both''' と呼ばれることもあります。マシンの状態をスワップ領域に保存しますが、マシンの電源を切りません。代わりに、デフォルトのサスペンドを呼び出します。これによって、バッテリーを使いきっても、システムは即座に復帰できます。バッテリーが枯渇した時は、システムはディスクから復帰し、RAM からの復帰に比べて時間がかかりますが、システムの状態が失われることはありません。
   
  +
カーネルは、基本的な機能を提供しており、問題のあるハードウェアドライバ/カーネルモジュール (例: ビデオカードの再初期化) に対処する機能を提供する高レベルなインターフェイスもいくつかあります。
* '''Suspend to both''' はマシンの状態をスワップ領域に保存しますが、マシンの電源を切りません。代わりに、通常の suspend to RAM を呼び出します。これによって、バッテリーを使いきっても、システムを RAM から復帰することが可能です。バッテリーが枯渇した時は、システムはディスクから復帰し、RAM からの復帰に比べて時間がかかりますが、システムの状態が失われることはありません。
 
   
  +
== カーネルのインターフェイス (swsusp) ==
基本的な機能を提供する低レベルなインターフェイス (バックエンド) が複数存在し、問題のあるハードウェアドライバ・カーネルモジュール (例: ビデオカードの再初期化) を扱う機能を提供する高レベルなインターフェイスもいくつかあります。
 
   
  +
{{Note|カーネルのインターフェイスを直接使用することは可能です (ユーザー空間で追加の処理が無いので高速です) が、[[#高レベルインターフェイス (systemd)|高レベルインターフェイス]]を使用することが推奨されます。このインターフェイスは、追加の安全性チェックを行い、さらに、ハードウェアクロックの修正や無線ネットワークの回復などをするためのサスペンド前後のフック機構を提供しているので、より優れています。}}
== 低レベルインターフェイス ==
 
   
  +
カーネル内のソフトウェアサスペンドコード (swsusp) にサスペンド状態に入るよう直接伝えることは可能です。実際の方法と状態はハードウェアサポートのレベルによります。最近のカーネルでは、サスペンドにするために {{ic|/sys/power/state}} に適切な文字列を書くことが主な方法になっています。
これらのインターフェイスは直接使うこともできますが、通常は[[#高レベルインターフェイス|高レベルインターフェイス]]を使ってサスペンド・ハイバネートを行うとよいでしょう。低レベルなインターフェイスを直接使うと、サスペンドの前や後に行うフック処理を全て実行する高レベルインターフェイスよりもかなり早くサスペンドが可能です。ただしフックはハードウェアクロックの設定や、ワイヤレスの復旧などを正しく処理することができます。
 
   
  +
詳しくは [https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation カーネルドキュメント] を参照してください。
=== カーネル (swsusp) ===
 
   
  +
== 高レベルインターフェイス (systemd) ==
直球の方法はカーネル内のソフトウェアサスペンドコード (swsusp) にサスペンド状態に入るよう直接伝えることです。実際の方法と状態はハードウェアサポートのレベルによります。最近のカーネルでは、サスペンドにするために {{ic|/sys/power/state}} に適切な文字列を書くことが主な方法になっています。
 
   
  +
{{Note|高レベルなインターフェイスの目的は、サスペンド/ハイバネートを行う際に利用できるバイナリ/スクリプトと、追加の準備/クリーンアップの作業を行うためのフックを実行する手段を提供することです。電源ボタンの押下、メニューのクリック、ノート PC の蓋イベントのときにスリープ状態に自動的に移行する方法については、[[電源管理#電源管理]] を見てください。}}
詳しくは [https://www.kernel.org/doc/Documentation/power/states.txt カーネルドキュメント] を参照してください。
 
   
  +
[[systemd]] は、サスペンド、ハイバネート、ハイブリッドサスペンドを行うためのネイティブなコマンドを提供しています。これは、Arch Linux で使用されるデフォルトのインターフェイスです。
=== uswsusp ===
 
   
  +
{{ic|systemctl suspend}} は、特に設定せずとも動くはずです。{{ic|systemctl hibernate}} に関しては、[[#ハイバネーション]] の手順に従わないと動作しないかもしれません。
uswsusp ('Userspace Software Suspend') はカーネルの suspend-to-RAM のラッパーで、サスペンドの前と復帰の後にユーザー空間からグラフィックアダプタの操作を行います。
 
   
  +
また、サスペンドとハイバネートを組み合わせたようなモードが2つあります:
[[Uswsusp]] の記事を参照してください。
 
   
  +
* {{ic|systemctl hybrid-sleep}} は、システムを RAM とディスクの両方にサスペンドします。なので、電源が完全に失われても、データ損失が発生しません。このモードは ''suspend to both'' とも呼ばれています。
== 高レベルインターフェイス ==
 
  +
* {{ic|systemctl suspend-then-hibernate}} は、最初は可能な限り長くシステムを RAM にサスペンドし、RTC アラームで復帰し、そしてハイバネートします。RTC アラームは {{man|5|systemd-sleep.conf}} 内の {{ic|HibernateDelaySec}} で設定します。デフォルトの値は、システムのバッテリーレベルが 5% に下がるまでの推定された時間に設定されます。システムにバッテリーが存在しない場合は、デフォルトで2時間に設定されます。推定時間は、{{man|5|systemd-sleep.conf}} 内の {{ic|SuspendEstimationSec}} によって指定された時間後のバッテリーレベルの変化から計算されます。{{ic|SuspendEstimationSec}} の時間後、システムは短い間サスペンドから復帰し、計測を行います (システムが手動でサスペンドから復帰された場合も、計測が行われます)。
   
  +
サスペンド/ハイバネートのフックの設定に関するその他の情報は、[[#スリープフック]] を見てください。また、{{man|1|systemctl}}、{{man|8|systemd-sleep}}、{{man|7|systemd.special}} も参照してください。
{{Note|これらのパッケージではサスペンド・ハイバネートを行うためのバイナリ・スクリプトを提供します。実際に電源ボタンやメニュークリック、ラップトップのカバーのイベントなどと結びつけるのは他のツールで行うのが通常です。(ラップトップのカバーが閉じられたり、バッテリーが枯渇するなど)特定の電源イベントで自動的にサスペンド・ハイバネートをするには、[[Acpid]] の実行について調べて下さい。}}
 
   
  +
== サスペンドの方法を変更する ==
=== systemd ===
 
   
  +
S0ix サスペンドが通常の S3 スリープと同じ節電機能を提供しないシステム、あるいは、電力を節約することが復帰を高速化することよりも優先される場合においては、デフォルトのサスペンド方法を変更することが可能です。
[[systemd]] はサスペンド・ハイバネート・ハイブリッドサスペンドを行うためのネイティブのコマンドを提供しています。詳しくは [[電源管理#systemd による電源管理]] を見て下さい。これは Arch Linux で使われているデフォルトのインターフェースです。
 
   
  +
{{Tip|S0ix は S3 スリープと同等かより高い節電性能を提供するはずです。意図通りに S0ix を機能させることができるかどうかは、次の Intel のブログ投稿を参照してください: [https://web.archive.org/web/20230614200816/https://01.org/blogs/qwang59/2018/how-achieve-s0ix-states-linux How to achieve S0ix states in Linux]、[https://web.archive.org/web/20230614200306/https://01.org/blogs/qwang59/2020/linux-s0ix-troubleshooting Linux S0ix Troubleshooting]、[https://01.org/blogs/thac0/2019/idling-efficiently-linux-case-study Idling Efficiently on Linux: A Case Study]。Intel システムでは [https://github.com/intel/S0ixSelftestTool S0ixSelftestTool] を使うことができます。}}
サスペンド・ハイバネートのフックの設定に関する情報は[[電源管理#スリープフック]]に載っています。{{ic|man systemctl}}, {{ic|man systemd-sleep}}, {{ic|man systemd.special}} もあわせて参照してください。
 
  +
  +
以下のコマンドは、ハードウェアによってサポートされていると広告されている全てのサスペンド方法を出力します (現在のサスペンド方法は角括弧に囲まれます[https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation]):
  +
  +
{{hc|$ cat /sys/power/mem_sleep|
  +
[s2idle] shallow deep
  +
}}
  +
  +
ハードウェアが {{ic|deep}} スリープ状態を広告していない場合、UEFI にそのような設定がないか確認してください。通常、''Power'' や ''Sleep state'' などのような項目にあります。S0ix のオプションは ''Windows 10'' や ''Windows and Linux'' や ''S3/Modern standby support'' という名前です。S3 スリープのオプションは ''Legacy''、''Linux''、''Linux S3''、''S3 enabled'' という名前です。設定できない場合、{{ic|s2idle}} を使い続けることもできます、[[ハイバネート]] を使うことを検討するか、[[DSDT]] テーブルにパッチを当ててみてください (あるいは、パッチ適用済みのバージョンを見つけてください)。
  +
  +
{{Note|最後の解決策は将来的に問題が発生する可能性があります。Windows を同梱しているシステムではデフォルトで "Modern standby" を使うよう推奨されているため、メーカーは ACPI S3 状態のバグの修正を停止しています。メーカーが自発的にそれを広告していない場合、おそらく、S3 状態は何らかの形で壊れています。}}
  +
  +
スリープの方法を変更したあと、スリープサイクルを何回かテストして、ハードウェアが S3 スリープで問題を起こさないかテストしてください:
  +
  +
# echo "deep" > /sys/power/mem_sleep
  +
  +
問題が無ければ、{{ic|1=mem_sleep_default=deep}} [[カーネルパラメータ]] を使って変更を永続化できます。
  +
  +
いくつかの逆の状況では、問題のあるファームウェアが {{ic|s2idle}} しかサポートしていないにも関わらず、{{ic|deep}} をサポートしていると広告することがあります。この場合、{{man|5|sleep.conf.d}} 内で {{ic|SuspendState}} を使うことにより、{{ic|s2idle}} を使うことができます:
  +
  +
{{hc|/etc/systemd/sleep.conf.d/freeze.conf|2=
  +
[Sleep]
  +
SuspendState=freeze
  +
}}
   
 
== ハイバネーション ==
 
== ハイバネーション ==
   
ハイバネーション使うには、[[スワップ]]パーティションかスワップファイル作成する必要がありますそして {{ic|1=resume=}} カネルパラメタを使ってワップ指定してください。カーネルパラメータはブートローダ設定しま[[#initramfs の設定|initramfs 設定]]も必要になります設定によってカーネルは初期ユーザー空間指定されたスワップから復帰試みま。以下はスワップの作成・カーネルパラメータ設定・initramfs 設定にいて詳細に説明ます。
+
ハイバネーうには、次のことを行う必要があります: [[スワップ]]パーティションかスワップファイル作成する。初期ユ空間で復帰プロセスを初期化きるようにるために [[#initramfs の設定|initramfs 設定する]]。Initramfs から利用できる方法でスワップ領域場所指定る (例えば、{{ic|HibernateLocation}} EFI 変数を [[systemd]] 定義したり、{{ic|1=resume=}} [[カーネルパラメータ]]を設定したり)。これら3の手順は以下で詳細に説明されています。
   
 
{{Note|
 
{{Note|
* [[ディスク暗号化]]を利用する場合は[[Dm-crypt/スワップの暗号化#suspend-to-disk を使用する]]を見てください。
+
* [[ディスク暗号化]]を利用する場合は[[dm-crypt/スワップの暗号化#suspend-to-disk を使用する]]を見てください。
 
* {{Pkg|linux-hardened}}はハイバネーションをサポートしていません。詳しくは{{Bug|63648}}を見てください。
 
* {{Pkg|linux-hardened}}はハイバネーションをサポートしていません。詳しくは{{Bug|63648}}を見てください。
  +
* zram 上のスワップへのハイバネートはサポートされていません。たとえ zram が永久記憶装置上のバッキングデバイスを使うように設定されていたとしてもです。''logind'' は、zram 上のスワップ領域へハイバネートしようとする試みから保護します。
 
}}
 
}}
   
  +
=== スワップパーティション(ファイル)のサイズについて ===
=== About swap partition/file size ===
 
  +
  +
スワップパーティションが RAM より小さかったとしても、ハイバネートが成功する可能性は高いと思われます。{{ic|image_size}} {{man|5|sysfs}} 疑似ファイルに関する情報は [https://docs.kernel.org/admin-guide/pm/sleep-states.html?highlight=image_size#basic-sysfs-interfaces-for-system-suspend-and-hibernation カーネルドキュメント]の "image_size" を見てください。
  +
  +
(スワップパーティションを小さくして) {{ic|/sys/power/image_size}} の値を減らしてサスペンドのイメージを出来る限り小さくすることも、値を増やしてハイバネーションを高速化することも可能です。大きな容量の RAM を搭載しているシステムでは、より小さい値にするとハイバネートからの復帰が劇的に速くなることがあります。{{ic|image_size}} の値を再起動後も保持するために [[systemd#systemd-tmpfiles - 一時ファイル]] を使うことができます:
  +
  +
{{hc|/etc/tmpfiles.d/hibernation_image_size.conf|
  +
# Path Mode UID GID Age Argument
  +
w /sys/power/image_size - - - - 0
  +
}}
  +
  +
サスペンドイメージは複数のスワップパーティション/スワップファイルにまたがって保存することができません。イメージのすべての部分が1つのスワップパーティション/スワップファイルに収まらなければなりません。[https://docs.kernel.org/power/swsusp.html]
  +
  +
=== initramfs の設定 ===
  +
  +
* Busybox ベースの [[initramfs]] を使用している場合 (Arch ではデフォルトです)、{{ic|/etc/mkinitcpio.conf}} に {{ic|resume}} フックを追加する必要があります。ラベルあるいは UUID どちらを使用している場合でもスワップパーティションは udev デバイスノードによって参照されるので、{{ic|resume}} フックは {{ic|udev}} フックの''後''に追加する必要があります。デフォルトのフック設定に {{ic|resume}} フックを追加すると以下のようになります:
  +
  +
:{{bc|1=HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block filesystems '''resume''' fsck)}}
  +
  +
:変更を適用するために [[mkinitcpio#イメージ作成とアクティベーション|initramfs の再生成]]を忘れずに行ってください。
  +
  +
:{{Note|スワップ領域にスタックされたストレージ (例えば、[[dm-crypt]]、[[RAID]]、[[LVM]]) を使用している場合は、最後のマッピングされるデバイスが、初期ユーザー空間内及び復帰プロセスの初期化前に利用できるようにする必要があります。つまり、どうすればよいかというと、{{ic|resume}} フックを {{ic|encrypt}} や {{ic|lvm2}} などのフックより後に置く必要があります (そのような環境である場合)。}}
  +
  +
* initramfs で {{ic|systemd}} フックを使っている場合は、復帰機構が既に提供されているので、フックを追加する必要はありません。
   
  +
=== ハイバネート先指定を initramfs に渡す ===
スワップパーティションが RAM より小さかったとしても、ハイバネートが成功する可能性は高いと思われます。{{ic|image_size}} {{man|5|sysfs}} 疑似ファイルに関する情報は [https://www.kernel.org/doc/html/latest/admin-guide/pm/sleep-states.html?highlight=image_size#basic-sysfs-interfaces-for-system-suspend-and-hibernation kernel documentation] の "image_size" を見てください。
 
   
  +
システムがハイバネートする際、メモリイメージがスワップ領域に保存されます (メモリイメージには、マウント済みファイルシステムの状態も含まれます)。そのため、ハイバネートから復帰できるようにするには、ハイバネート先がどこであるかという情報が、initramfs で (つまり、ルートファイルシステムがマウントされる前の時点で) 利用できるようにする必要があります。
(スワップパーティションを小さくして) {{ic|/sys/power/image_size}} の値を減らしてサスペンドのイメージを出来る限り小さくすることも、値を増やしてハイバネーションを高速化することも可能です。大きな容量の RAM を搭載しているシステムでは、より小さい値にするとハイバネートからの復帰が劇的に速くなることがあります。{{ic|image_size}} の値を再起動後も保持するには [[systemd#systemd-tmpfiles - 一時ファイル]] を見てください。
 
   
  +
{{Pkg|systemd}} v255 及び {{Pkg|mkinitcpio}} v38 からは、システムが [[UEFI]] 上で実行されている場合、{{man|8|systemd-sleep}} はハイバネート先として適切なスワップ領域を自動的に選択し、使用されたスワップ領域の情報は {{ic|HibernateLocation}} EFI 変数に格納されます。次回のブート時には、{{man|8|systemd-hibernate-resume}} がこの EFI 変数からスワップ領域の場所を読み込み、システムが復帰します。よって、システムがレガシー [[Arch ブートプロセス#BIOS|BIOS]] を使用している場合や、あなたが自動的に選択されるスワップ領域とは別のスワップ領域を使用したい場合を除いて、以下の手順は必須ではありません。
サスペンドイメージは複数のスワップパーティション/スワップファイルにまたがって保存することができません。イメージのすべての部分が1つのスワップパーティション/スワップファイルに収まらなければなりません。[https://www.kernel.org/doc/html/latest/power/swsusp.html]
 
   
  +
==== ハイバネート先を手動で指定する ====
=== 必要なカーネルパラメータ ===
 
   
[[カーネルパラメータ]] {{ic|1=resume=''swap_device''}} を使う必要があります。[[永続的なブロックデバイスの命名]]を {{ic|''swap_device''}} 使用することができます。例:
+
[[カーネルパラメータ]] {{ic|1=resume=''swap_device''}} を使用することで可能です。''swap_device'' は[[永続的なブロックデバイスの命名]]に従います。例えば:
   
 
* {{ic|1=resume=/dev/sda1}}
 
* {{ic|1=resume=/dev/sda1}}
 
* {{ic|1=resume=UUID=4209c845-f495-4c43-8a03-5363dd433153}}
 
* {{ic|1=resume=UUID=4209c845-f495-4c43-8a03-5363dd433153}}
* {{ic|1=resume=/dev/mapper/archVolumeGroup-archLogicVolume}} -- スワップが [[LVM]] 論理ボリュームにある場合
+
* {{ic|1=resume=/dev/mapper/archVolumeGroup-archLogicVolume}} スワップが [[LVM]] 論理ボリュームにある場合 (UUID や Label も使えるはずです)
   
[[カーネルパラメータ]]は再起動後に有効となります。すぐにハイバネートできるようにするには、[[lsblk]] を使ってボリュームのメジャーデバイスナンバーとマイナーデバイスナンバーを手に入れて、{{ic|/sys/power/resume}} に {{ic|''major'':''minor''}} という形式で書き込んでください。スワップファイルを使用している場合は、追加で {{ic|/sys/power/resume_offset}} に resume オフセットを書き込んでください。[https://www.kernel.org/doc/html/latest/power/swsusp.html]
+
[[カーネルパラメータ]]は再起動後に有効となります。すぐにハイバネートできるようにするには、[[lsblk]] を使ってボリュームのメジャーデバイスナンバーとマイナーデバイスナンバーを手に入れて、{{ic|/sys/power/resume}} に {{ic|''major'':''minor''}} という形式で書き込んでください。
   
 
例えば、スワップデバイスが {{ic|8:3}} の場合:
 
例えば、スワップデバイスが {{ic|8:3}} の場合:
76行目: 129行目:
 
# echo 8:3 > /sys/power/resume
 
# echo 8:3 > /sys/power/resume
   
スワップファイルにハイバネートする場合、スワップファイルがボリューム {{ic|8:2}} にあり、オフセットが {{ic|38912}}場合:
+
スワップファイルを使用する場合、これに加えて [[#スワップファイルオフセットを手に入れる]]手順も行ってください。
   
  +
===== スワップファイルのオフセットを手に入れる =====
# echo 8:2 > /sys/power/resume
 
# echo 38912 > /sys/power/resume_offset
 
 
==== スワップファイルにハイバネーション ====
 
   
{{Warning|バージョン5.0以前のLinuxカーネルでは [[Btrfs#スワップファイル|Btrfs]] はスワップファイルをサポートしていません。この警告に従わない場合、ファイルシステムが破損すおそれがあります。ループデバイスを経由してマウントしているときに Btrfs でスワップファイルを使うと、スワフォマンス著しく低下してしまいます。}}
+
[[スワップファイル]]をハイバネート用に使用する場合、(スワップファイルが存在している) ファイルシステムを含んでいブロックデバイスを {{ic|1=resume=}}指定する必要があり、さらに、スワップファイルの物理オフセトも {{ic|1=resume_offset=}} [[カーネルラメタ]]で指定する必要あります。[https://docs.kernel.org/power/swsusp-and-swap-files.html]
   
  +
[[Btrfs]] 以外のファイルシステムでは、{{ic|1=resume_offset=}} の値は {{ic|filefrag -v ''swap_file''}} を実行することで得られます。このコマンドは表を出力します。必要な値は {{ic|physical_offset}} 列の最初の行にあります。
[[スワップ#手動設定|スワップファイル]] を使用するには {{ic|1=resume=''swap_device''}} だけでなく、{{ic|1=resume_offset=''swap_file_offset''}} カーネルパラメータも設定する必要があります。[https://www.kernel.org/doc/html/latest/power/swsusp-and-swap-files.html カーネルのドキュメント]を見てください。
 
   
  +
例えば:
{{ic|''swap_device''}} はスワップファイルが存在するボリュームで、[[永続的なブロックデバイスの命名#ブートマネージャ|root パラメータ]]と同じ形式に従います。{{ic|''swap_file_offset''}} の値は {{ic|filefrag -v ''swap_file''}} を実行することで取得できます。テーブル形式で出力され、必要な値は {{ic|physical_offset}} カラムの一番上の段にあります。例えば:
 
   
 
{{hc|# filefrag -v /swapfile|
 
{{hc|# filefrag -v /swapfile|
99行目: 149行目:
 
}}
 
}}
   
この例では {{ic|''swap_file_offset''}} の値は2つのピリオドが付いている最初の {{ic|38912}} す。
+
この例では{{ic|1=resume_offset=}} の値は最初の {{ic|38912}} になります。
   
  +
あるいは、オフセットの値を直接手に入れるには:
{{Tip|
 
* 次のコマンドは {{ic|''swap_device''}} を特定するのに利用できます: {{ic|1=findmnt -no UUID -T /swapfile}}
 
* 次のコマンドは {{ic|''swap_file_offset''}} を特定するのに利用できます: {{ic|1=filefrag -v /swapfile {{!}} awk '$1=="0:" {print substr($4, 1, length($4)-2)}'}}
 
* {{ic|''swap_file_offset''}} の値は {{ic|swap-offset ''swap_file''}} を実行することによっても得られます。 ''swap-offset'' バイナリは [[uswsusp]] ツールのセットで提供されています。 もしこの方法を利用するならば、これら2つのパラメータは {{ic|/etc/suspend.conf}} 内で {{ic|resume device}} と {{ic|resume offset}} というキーで渡されなければなりません。この場合、再起動は必要ありません。
 
}}
 
   
  +
# filefrag -v ''swap_file'' | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
{{Note|
 
* 暗号化コンテナ (LUKS)、 RAID、 LVM のようなスタックブロックデバイスでは、{{ic|resume}} パラメータはスワップファイルのあるファイルシステムを含んでいる、アンロックまたはマップされたデバイスを指していなければなりません。
 
* スワップファイルが {{ic|/home/}} に存在する場合、''systemd-logind'' はスワップファイルのサイズを正しく判断することができないため、以下のメッセージによりハイバネートを停止します: {{ic|Failed to hibernate system via logind: Not enough swap space for hibernation}}。2つの回避策については [https://github.com/systemd/systemd/issues/15354 systemd issue 15354] をご覧ください。}}
 
   
  +
[[Btrfs]] の場合、''filefrag'' ツールは使わないでください。''filefrag'' から得られる "physical" オフセットの値は、ディスク上の実際の物理オフセットとは異なるからです。複数のデバイスをサポートするために、仮想的なディスクアドレス空間が存在するのです。[https://bugzilla.kernel.org/show_bug.cgi?id=202803] 代わりに、{{man|8|btrfs-inspect-internal}} コマンドを使ってください。例えば:
{{Tip|スワップファイルを作成する目的が、仮想メモリの拡張ではなくハイバネートがしたいだけの場合、スワップファイルの [[スワップ#Swappiness|Swappiness]] を減らすとよいでしょう。}}
 
   
  +
{{hc|# btrfs inspect-internal map-swapfile -r ''swap_file''|
==== Btrfs のスワップファイルへのハイバネーション ====
 
  +
198122980
  +
}}
   
  +
この例では、カーネルパラメータは {{ic|1=resume_offset=198122980}} となります。
スワップファイルへの休止状態は、systemd の最近のバージョン [https://github.com/systemd/systemd/issues/9559] でサポートされています。
 
   
  +
再起動せずにこの変更を即座に適用するには、resume offset を {{ic|/sys/power/resume_offset}} に書き込んでください。例えば、オフセットが {{ic|38912}} である場合は:
resume_offset 番号は、 [https://github.com/osandov/osandov-linux/blob/master/scripts/btrfs_map_physical.c tool btrfs_map_physical.c] を使用して計算できます。
 
[[Btrfs]] では、 filefrag ツールを使用しないでください。 filefrag から取得する ''物理的'' オフセットは、ディスク上の実際の物理的オフセットではありません。 複数のデバイスをサポートするために、仮想ディスクのアドレス空間があります。 [https://bugzilla.kernel.org/show_bug.cgi?id=202803]
 
   
  +
# echo 38912 > /sys/power/resume_offset
[https://github.com/osandov/osandov-linux/blob/master/scripts/btrfs_map_physical.c tool btrfs_map_physical.c] をダウンロードするか、 {{ic|btrfs_map_physical.c}} という名前のファイルにコピーしてからコンパイルします。
 
   
  +
{{Tip|次のコマンドは、スワップファイルのバッキングデバイスを特定する際に使用できます: {{ic|1=findmnt -no UUID -T ''swap_file''}}}}
$ gcc -O2 -o btrfs_map_physical btrfs_map_physical.c
 
   
  +
{{Note|暗号化コンテナ (LUKS)、 RAID、 LVM のようなスタックブロックデバイスでは、{{ic|resume}} パラメータはスワップファイルのあるファイルシステムを含んでいる、アンロックまたはマップされたデバイスを指していなければなりません。}}
そしてそれを実行します。 出力例を以下に示します。
 
   
  +
==== ハイバネート用のスワップファイルを zram で保持する ====
{{hc|# ./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
 
}}
 
   
  +
{{Tip|以下の方法は複数のスワップ領域を使用しますが、[[zswap]] を使えば似たようなことをすることができます。}}
このツールによって返される最初の物理オフセットに注意してください。 この例では、 {{ic|4009762816}} を使用します。 {{ic|getconf PAGESIZE}} で見つけることができるページサイズにも注意してください。
 
   
  +
RAM 圧縮 (zram) でのハイバーネートの問題は、複数のスワップ領域を同時に保持することで解決できます。[[Systemd]] は、ハイバネートをトリガーする前に zram ブロックデバイスを常に無視するので、特に設定せずに両方の領域 (スワップファイルと zram) を保持できるはずです。
{{ic|resume_offset}} 値を計算するには、物理オフセットをページサイズで割ります。 この例では、 {{ic|1=4009762816 / 4096 = 978946}} です。
 
  +
  +
[[#スワップファイルのオフセットを手に入れる|スワップファイルの設定]]が済んだら、[[zram]] のページの手順に従ってください。このとき、zram に'''高いスワップ優先度''' (例えば {{ic|1=pri=100}}) を割り当ててください。
  +
  +
{{Note|
  +
* ハイバネート用のオンデマンドのスワップユニットは作成'''しないでください'''。これは公式にはサポートされていません。Systemd の issue [https://github.com/systemd/systemd/issues/16708 #16708] と [https://github.com/systemd/systemd/issues/30083 #30083] を参照してください。
  +
* カーネルは無名 (anonymous) ページの回収とスワップを行います。スワップ領域を利用しないと、メモリ使用効率の悪化につながる可能性があります。ユーザーは、{{ic|memory.low}} によって特定のアプリケーションにおけるメモリ回収の優先度を管理することができます (これは[[コントロールグループ]]で調整可能です)。全体として、この方が [[swappiness]] パラメータを設定するよりも効率的です。
  +
* 詳細は[https://www.kernel.org/doc/gorman/html/understand/understand014.html カーネルドキュメントの Swap Management 章]と [https://chrisdown.name/2018/01/02/in-defence-of-swap.html Chris Down の - In defence of swap: common misconceptions] (Hiroaki Nakamura による日本語訳: [https://chrisdown.name/ja/2018/01/02/in-defence-of-swap.html スワップの弁護:よくある誤解を解く]) を参照してください。
  +
}}
   
 
==== thinly-provisioned LVM ボリュームへのハイバネーション ====
 
==== thinly-provisioned LVM ボリュームへのハイバネーション ====
152行目: 195行目:
 
ボリュームが完全に割り当てられていることを確認するには、次を使用できます:
 
ボリュームが完全に割り当てられていることを確認するには、次を使用できます:
   
{{hc|# lvs|
+
{{hc|# lvs|
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
+
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
swap vg0 Vwi-aot--- 10.00g pool 100
+
swap vg0 Vwi-aot--- 10.00g pool 100
 
}}
 
}}
   
161行目: 204行目:
 
{{Warning|休止状態に使用される thinly-provisioned されたスワップボリュームで [[TRIM]] を使用しないでください。つまり、 {{ic|/etc/fstab}} で {{ic|discard}} を使用しないでください。 ''swapon'' の {{ic|-d}}/{{ic|--discard}} オプション。 そうしないと、使用済みスペースの割り当てが解除されます。}}
 
{{Warning|休止状態に使用される thinly-provisioned されたスワップボリュームで [[TRIM]] を使用しないでください。つまり、 {{ic|/etc/fstab}} で {{ic|discard}} を使用しないでください。 ''swapon'' の {{ic|-d}}/{{ic|--discard}} オプション。 そうしないと、使用済みスペースの割り当てが解除されます。}}
   
  +
== スリープフック ==
=== initramfs の設定 ===
 
   
  +
=== カスタムの systemd ユニット ===
* [[initramfs]] で {{ic|base}} フックを使っている場合 (Arch ではデフォルトで使っています)、{{ic|/etc/mkinitcpio.conf}} に {{ic|resume}} フックを追加する必要があります。ラベルあるいは UUID どちらを使用している場合でもスワップパーティションは udev デバイスノードによって参照されるので、{{ic|resume}} フックは必ず {{ic|filesystems}} の前に追加してください。デフォルトのフック設定に {{ic|resume}} フックを追加すると以下のようになります:
 
   
  +
[[systemd]] は、スリープ状態に応じて {{ic|suspend.target}}、{{ic|hibernate.target}}、{{ic|hybrid-sleep.target}}、{{ic|suspend-then-hibernate.target}} のどれかを開始します。これらの target は全て、{{ic|sleep.target}} も開始します。これらの target はどれも、サスペンド/ハイバネートの前や後に[[systemd#ユニットファイル|カスタムのユニット]]を実行するために使用することができます。ユーザーのアクション用と root ユーザー/システムのアクション用とで、別々のファイルを作成する必要があります。例えば:
:{{bc|1=HOOKS="base udev autodetect modconf block '''resume''' filesystems keyboard fsck"}}
 
   
  +
{{hc|/etc/systemd/system/user-suspend@.service|2=
:変更を適用するために [[mkinitcpio#イメージ作成とアクティベーション|initramfs の再生成]]を忘れずに行ってください。
 
  +
[Unit]
  +
Description=User suspend actions
  +
Before=sleep.target
   
  +
[Service]
:{{Note|[[LVM]] を使っている場合は {{ic|resume}} フックを {{ic|lvm2}} の後に追加してください。}}
 
  +
User=%I
  +
Type=forking
  +
Environment=DISPLAY=:0
  +
ExecStartPre= -/usr/bin/pkill -u %u unison ; /usr/local/bin/music.sh stop
  +
ExecStart=/usr/bin/sflock
  +
ExecStartPost=/usr/bin/sleep 1
   
  +
[Install]
* initramfs で {{ic|systemd}} フックを使っている場合は、復帰機構が既に提供されているので、フックを追加する必要はありません。
 
  +
WantedBy=sleep.target
  +
}}
  +
  +
{{hc|/etc/systemd/system/user-resume@.service|2=
  +
[Unit]
  +
Description=User resume actions
  +
After=suspend.target
  +
  +
[Service]
  +
User=%I
  +
Type=simple
  +
ExecStart=/usr/local/bin/ssh-connect.sh
  +
  +
[Install]
  +
WantedBy=suspend.target
  +
}}
  +
  +
変更を適用するには、{{ic|user-suspend@''user''.service}} や {{ic|user-resume@''user''.service}} を有効化してください。
  +
  +
{{Note|スクリーンが"ロックされる"前にスクリーンロックが返ってきてしまい、サスペンドから復帰するときに画面が点滅することがあります。{{ic|1=ExecStartPost=/usr/bin/sleep 1}} で小さな遅延を追加することでこれを防止できます。}}
  +
  +
root ユーザー/システムのアクション用:
  +
  +
{{hc|/etc/systemd/system/root-suspend.service|2=
  +
[Unit]
  +
Description=Local system suspend actions
  +
Before=sleep.target
  +
  +
[Service]
  +
Type=simple
  +
ExecStart=-/usr/bin/pkill sshfs
  +
  +
[Install]
  +
WantedBy=sleep.target
  +
}}
  +
  +
{{hc|/etc/systemd/system/root-resume.service|2=
  +
[Unit]
  +
Description=Local system resume actions
  +
After=suspend.target
  +
  +
[Service]
  +
Type=simple
  +
ExecStart=/usr/bin/systemctl restart mnt-media.automount
  +
  +
[Install]
  +
WantedBy=suspend.target
  +
}}
  +
  +
==== スリープ/復帰のユニットの統合 ====
  +
  +
サスペンド/レジュームのサービスファイルを統合すれば、様々なフェイズ (スリープ/レジューム) やターゲット (サスペンド/ハイバネート/ハイブリッドスリープ) でやることをひとつのフックで行うことができます。
  +
  +
例と説明:
  +
  +
{{hc|/etc/systemd/system/wicd-sleep.service|2=
  +
[Unit]
  +
Description=Wicd sleep hook
  +
Before=sleep.target
  +
StopWhenUnneeded=yes
  +
  +
[Service]
  +
Type=oneshot
  +
RemainAfterExit=yes
  +
ExecStart=-/usr/share/wicd/daemon/suspend.py
  +
ExecStop=-/usr/share/wicd/daemon/autoconnect.py
  +
  +
[Install]
  +
WantedBy=sleep.target
  +
}}
  +
  +
* {{ic|1=RemainAfterExit=yes}}: 起動後、明示的に止められるまでサービスは常時 active とみなされます。
  +
* {{ic|1=StopWhenUnneeded=yes}}: active 時、他のサービスから必要とされなくなった場合、サービスは停止されます。この例では、{{ic|sleep.target}} が停止されるとこのサービスは停止されます。
  +
* {{ic|sleep.target}} では {{ic|1=StopWhenUnneeded=yes}} が設定されているため、このフックは別のタスクにおいても適切に開始/停止することが保証されます。
  +
  +
=== /usr/lib/systemd/system-sleep のフック ===
  +
  +
{{Note|{{man|8|systemd-sleep}} によれば、この方法は systemd ではハックなやり方だとされています。''systemd-sleep'' は、これらのフックを1つずつではなく並列に実行します。順序実行がサポートされている、より明確に定義されたインターフェイスについては、[[#カスタムの systemd ユニット]] をみてください。}}
  +
  +
''systemd-sleep'' は、{{ic|/usr/lib/systemd/system-sleep/}} 内の全ての実行可能ファイルを実行します。このとき、2つの引数が渡されます:
  +
  +
# {{ic|pre}} または {{ic|post}}: マシンがスリープしようとしているのか、復帰しようとしているのか。
  +
# {{ic|suspend}}、{{ic|hibernate}}、{{ic|hybrid-sleep}} のどれか: どのスリープ状態が実行される/されたのか。
  +
  +
カスタムスクリプトの出力は、''systemd-suspend.service'' や ''systemd-hibernate.service''、''systemd-hybrid-sleep.service'' によって記録されます。''systemd'' の [[journalctl]] でこのログを見ることができます:
  +
  +
# journalctl -b -u systemd-suspend.service
  +
  +
カスタムのスリープスクリプト例:
  +
  +
{{hc|/usr/lib/systemd/system-sleep/example.sh|
  +
#!/bin/sh
  +
case $1/$2 in
  +
pre/*)
  +
echo "Going to $2..."
  +
;;
  +
post/*)
  +
echo "Waking up from $2..."
  +
;;
  +
esac
  +
}}
  +
  +
スクリプトを[[実行可能属性|実行可能]]にするのを忘れないで下さい。
  +
  +
== ヒントとテクニック ==
  +
  +
=== スリープを完全に無効化する ===
  +
  +
デバイスをサーバなどとして使用している場合、サスペンドは必要ないかもしれませんし、かえって望ましくない可能性もあります。{{man|5|systemd-sleep.conf}} を使えば任意のスリープ状態を無効化することができます:
  +
  +
{{hc|/etc/systemd/sleep.conf.d/disable-suspend.conf|2=
  +
[Sleep]
  +
AllowSuspend=no
  +
AllowHibernation=no
  +
AllowHybridSleep=no
  +
AllowSuspendThenHibernate=no
  +
}}
  +
  +
=== Intel Rapid Start Technology (IRST) ===
  +
  +
Intel Rapid Start Technology とは、ハイバネートするためのハードウェア上の方法で、あらかじめ設定された時間の後やバッテリー状態に基づいてスリープからハイバネートに移行できるようにします。IRSTは、オペレーティングシステムのレベルではなくファームウェアによって行われるので、通常のハイバネートよりも速く信頼性が高いはずです。一般的に、IRST はファームウェアで有効化する必要があり、またファームウェアで、サスペンド/バッテリイベント後にハイバネートをトリガーするまでの時間を設定できます。しかし、一部のデバイスは IRST をファームウェアでサポートしていますが、Intel の Windows ドライバからでしか設定できません。そのような場合には、以下で説明している intel-rst カーネルモジュールで Linux でもイベントを設定できるはずです。
  +
  +
Intel Rapid Start Technology (IRST) が有効の場合、deep sleep からの再開には "[https://mjg59.dreamwidth.org/26022.html S3から再開するよりも数秒長くなりますが、ハイバネートから再開するよりもはるかに高速です]"。
   
  +
Intel ベースのシステムの多くは、 IRST のファームウェアをサポートしていますが、(HDD ではなく) SSD 上に特別なパーティションを必要とします。 Windows の OEM 展開では、Arch Linux インストールプロセス中に (SSD 全体を消去して再パーティションするのではなく) 保持できる IRST パーティションがすでに存在している場合があります。システムの RAM と同じサイズの未フォーマットパーティションとして表示されます。
== Intel Rapid Start Technology (IRST) ==
 
   
  +
{{Warning|Intel Rapid Start パーティションは暗号化されていません。「Intel は、あなたがソフトウェアベースのディスク暗号化を使用している場合、Intel Rapid Start Technology を無効化することを推奨します。」[https://www.intel.com/content/www/us/en/support/articles/000024080/technologies.html]}}
Intel Rapid Start Technology (IRST) が有効の場合、 deep sleep からの再開には "[https://mjg59.dreamwidth.org/26022.html S3から再開するよりも数秒長くなりますが、休止状態から再開するよりもはるかに高速です]"。
 
   
  +
ドライブ全体を消去してパーティションを切り直すつもりなら (あるいはすでにそうしてしまっているなら) IRST パーティションも再作成しなければなりません。これを行うには、システムの RAM と同じサイズの空のパーティションを作成し、そのパーティションの種類が GPT パーティションの場合は [[Wikipedia:GUID Partition Table#Partition type GUIDs|GUID]] {{ic|D3BFE2DE-3DAF-11DF-BA40-E3A556D89593}} に、 MBR パーティションの場合は [https://en.wikipedia.org/wiki/Partition_type ID] {{ic|0x84}} に設定します。また、システムのファームウェア設定で IRST のサポートを有効にする必要がある場合もあります。
Intel ベースのシステムの多くは、 IRST のファームウェアをサポートしていますが、 (HDDではなく) SSD 上に特別なパーティションを必要とします。 Windows の OEM 展開では、Arch Linux インストールプロセス中に (SSD 全体を消去して再パーティションするのではなく) 保持できる IRST パーティションがすでに存在している場合があります。システムの RAM と同じサイズの未フォーマットパーティションとして表示されます。
 
   
  +
{{Tip|(サスペンド後に)IRST が開始されるまでの時間は、システムのファームウェア設定で調整できます。}}
{{Warning|Intel Rapid Start パーティションは暗号化されていません。}}
 
   
  +
IRST ハイバネートにかかる時間 (つまり、"RAMの内容全体を特殊なパーティションに" コピーする時間) は、システムの RAM サイズと SSD 速度によって異なり、20~60秒かかります。システムによっては、プロセスの完了を(点滅を止めるなどして) LED インジケータで示す場合があります。
しかし、ドライブ全体を消去してパーティションを切り直すつもりなら (あるいはすでにそうしてしまっているなら) IRST パーティションも再作成しなければなりません。これを行うには、システムの RAM と同じサイズの空のパーティションを作成し、そのパーティションの種類が GPT パーティションの場合は [[Wikipedia:GUID Partition Table#Partition type GUIDs|GUID]] {{ic|D3BFE2DE-3DAF-11DF-BA40-E3A556D89593}} に、 MBR パーティションの場合は [https://en.wikipedia.org/wiki/Partition_type ID] {{ic|0 x 84}} に設定します。また、システムのファームウェア設定で IRST のサポートを有効にする必要がある場合もあります。
 
   
  +
Linux カーネルで IRST ハイバネートイベントを設定するには、{{ic|CONFIG_INTEL_RST}} オプションでカーネルに組み込むか、カーネルモジュールとして利用可能である必要があります。{{ic|modprobe intel_rst}} を実行してモジュールをロードすれば、{{ic|/sys/bus/acpi/drivers/intel_rapid_start/*/}} にファイル {{ic|wakeup_events}} と {{ic|wakeup_time}} が生成されるはずです。これらを用いて、さらなる設定を行うことができます。このモジュールは簡潔にドキュメント化されています。詳細は [https://github.com/torvalds/linux/blob/143a6252e1b8ab424b4b293512a97cca7295c182/drivers/platform/x86/intel/rst.c drivers/platform/x86/intel/rst.c] を見てください。
{{Tip|IRST が開始されるまでの時間 (サスペンド後) は、システムのファームウェア設定で調整できます。}}
 
   
  +
Intel Rapid Start Technology に関する情報は、[https://www.intel.com/content/www/us/en/support/articles/000024078/technologies.html general Q&A] と [https://www.intel.com/content/www/us/en/support/articles/000024273/technologies/intel-vpro-platform.html?wapkw=user%20guide%20Intel%20rapid%20start%20 user guides] も見てください。
IRST 休止状態プロセスの時間 ("RAMの内容全体を特殊なパーティションに" コピー) は、システムの RAM サイズと SSD 速度によって異なり、20~60秒かかります。システムによっては、プロセスの完了を LED インジケータで示す場合があります (点滅が停止した場合など)
 
   
 
== トラブルシューティング ==
 
== トラブルシューティング ==
195行目: 370行目:
 
=== サスペンド/ハイバネートが動作しない、あるいはたまに動作しなくなる ===
 
=== サスペンド/ハイバネートが動作しない、あるいはたまに動作しなくなる ===
   
サスペンドやハイバネートをした場合、あるいは復帰した場合に画面が表示されなくなるという報告が多数存在します。ノートパソコンとデスクトップの両方で問題は確認されています。解決方法ではありませんが、古いカーネル、特に LTS カーネルに切り替えることで問題解決することがあります。
+
ハイバネートやサスペンドから復帰したに画面が真っ暗になって、明確なエラーは表示されず、何もできなくなるという報告が多数存在します。これらの問題は、ノートパソコンとデスクトップの両方で確認されています。解決方法ではありませんが、古いカーネル、特に LTS カーネルに切り替えることで問題解決することがあります。
   
  +
ハードウェアの watchdog タイマーを使用している場合に問題が起こることもあります (デフォルトで無効化されています、{{man|5|systemd-system.conf|OPTIONS}} の {{ic|1=RuntimeWatchdogSec=}} を見てください)。バグのある watchdog タイマーにより、システムがハイバネートイメージの作成を終える前に、コンピュータがリセットされることがあります。
initramfs からのデバイスの初期化によって画面が表示されなくなっていることもあります。[[Mkinitcpio#MODULES]] に追加したモジュールを削除して initramfs を再生成することで問題が解決するかもしれません。特にグラフィックドライバの[[Kernel_Mode_Setting#Early_KMS_start|モジュール]]は問題を起こしがちです。復帰するまえにデバイスが初期化されると矛盾状態になってシステムがハイバネートから復帰できなくなります。サスペンドからの復帰の場合は関係ありません。サスペンドやハイバネートの問題をデバッグする際のベストプラクティスが [https://01.org/blogs/rzhang/2015/best-practice-debug-linux-suspend/hibernate-issues こちらの記事] に記載されています。
 
  +
  +
時々、initramfs 内からのデバイスの初期化によって黒画面が発生することがあります。[[Mkinitcpio#MODULES]] 内にあるモジュールを削除し、{{ic|kms}} フックを削除し、initramfs を再ビルドすると、この問題を解決できる可能性があります (特に、[[カーネルモード設定#KMS の早期開始|KMS の早期開始]]が設定されたグラフィックスドライバの場合)。復帰前にそのようなデバイスを初期化すると、整合性がなくなり、システムのハイバネートからの復帰を妨げてしまう可能性があります。これは RAM からの復帰には影響しません。また、ブログ記事 [https://web.archive.org/web/20230502010825/https://01.org/blogs/rzhang/2015/best-practice-debug-linux-suspend/hibernate-issues best practices to debug suspend issues] も確認してください。
  +
  +
[[ATI]] ビデオドライバから新しい [[AMDGPU]] ドライバに移行すると、ハイバネートと復帰のプロセスを成功させることができる可能性があります。
  +
  +
[[NVIDIA]] ユーザは、{{ic|nvidiafb}} モジュールを[[ブラックリスト|ブラックリスト化]]すると、問題が解決するかもしれません。[https://bbs.archlinux.org/viewtopic.php?id=234646]
  +
  +
Intel CPU を搭載していて、タッチパッドのために {{ic|intel_lpss_pci}} をロードするノート PC では、復帰時にカーネルパニックを引き起こすことがあります(この時、caps lock が点滅する) [https://bbs.archlinux.org/viewtopic.php?id=231881]。このモジュールは、以下のように [[initramfs]] に追加する必要があります:
  +
  +
{{hc|/etc/mkinitcpio.conf|2=
  +
MODULES=(... intel_lpss_pci ...)
  +
}}
  +
  +
そして、[[initramfs を再生成する|initramfs を再生成]]してください。
   
 
=== Wake-on-LAN ===
 
=== Wake-on-LAN ===
205行目: 394行目:
 
=== サスペンドからすぐに復帰する ===
 
=== サスペンドからすぐに復帰する ===
   
  +
[[電源管理/復帰トリガー#サスペンドからすぐに復帰する]] を見てください。
LynxPoint や LynxPoint-LP チップセットが搭載された Intel Haswell の場合、サスペンドからすぐに復帰してしまうと報告されています。BIOS の ACPI 実装に問題があり起動時に {{ic|xhci_hcd}} モジュールによって ACPI イベントが解釈されてしまうのが原因です。解決策としてカーネルによってケースバイケースで問題のあるシステムがブラックリスト ({{ic|XHCI_SPURIOUS_WAKEUP}}) に追加されています [https://bugzilla.kernel.org/show_bug.cgi?id=66171#c6]。
 
   
  +
AMD CPU 上で Linux カーネル 6.1 以上を使用している場合、これは[https://gitlab.freedesktop.org/drm/amd/-/issues/2357 カーネル内の S3 関連の制御ポリシーの問題]が原因である可能性もあります。一時的な解決策は、関連する i2c デバイスの復帰をオフにすることです。関連する i2c デバイスは以下のコマンドで見つけられます:
サスペンド中に USB デバイスを接続したときなどに ACPI の復帰トリガーが有効になって復帰してしまいます。ブラックリストに追加されるまで一時的な応急処置としては復帰トリガーを無効化する方法があります。以下の設定で USB による復帰を無効化することができます [https://bbs.archlinux.org/viewtopic.php?pid=1575617]。
 
   
  +
$ ls /sys/bus/i2c/devices/*/power/wakeup
現在の設定を確認:
 
  +
  +
デバイス名の形式は {{ic|i2c-ELAN0679:00}} や {{ic|i2c-MSFT0001:00}} であるはずです。次に、以下のコマンドでサスペンドに移行できるかテストします:
  +
  +
# echo disabled > /sys/bus/i2c/devices/''device_name''/power/wakeup
  +
# systemctl suspend
  +
  +
これでうまく行くならば、udev ルールを追加することで、この設定を永続化できます:
  +
  +
{{hc|/etc/udev/rules.d/99-avoid-i2c-wakeup.rules|2=KERNEL=="''device_name''", SUBSYSTEM=="i2c", ATTR{power/wakeup}="disabled"}}
  +
  +
=== ハイバネートした時にシステムの電源が落ちない ===
  +
  +
システムをハイバネートした時には、(状態をディスク上に保存したあとに)システムの電源が落ちるはずです。時々、ハイバネートした後も電源 LED が光り続けることがあります。これが起こる場合、{{man|5|sleep.conf.d}} で {{ic|HibernateMode}} を {{ic|shutdown}} に設定すると問題が解決するかもしれません。
  +
  +
{{hc|/etc/systemd/sleep.conf.d/hibernatemode.conf|2=
  +
[Sleep]
  +
HibernateMode=shutdown
  +
}}
  +
  +
上記の設定により、その他の設定が正しく行われていれば、{{ic|systemctl hibernate}} を実行するとマシンがシャットダウンし、状態をディスクに保存します。
  +
  +
=== ハイバネート後に起動するとオペレーティングシステムが見つからない (または、間違った OS が起動する) ===
  +
  +
これは、ブートディスクが外部ディスクである場合に起こる可能性があります。BIOS/ファームウェアの制限が原因であるようです。ハイバネーションは外部 (あるいは別の) ディスク上の OS から行われたが、BIOS/ファームウェアは内部ディスクから起動を試みてしまっているのです。
  +
  +
[[#ハイバネートした時にシステムの電源が落ちない]] で説明したように {{ic|1=HibernateMode=shutdown}} を設定することで、この問題を永久に解決できます。すでにシステムから締め出されてしまっている場合、システムを4回再起動 (毎回、エラーが表示されるまで待ってください) してみることで、一部の BIOS 上では通常のブート手順を強制することができます。
  +
  +
=== /home にスワップファイルを置く ===
  +
  +
スワップファイルが {{ic|/home/}} にある場合、''systemd-logind'' はスワップファイルにアクセスできず、{{ic|Call to Hibernate failed: No such file or directory}} という警告メッセージを出力して、{{ic|systemctl hibernate}} の実行時に認証を求められます。このようなセットアップは、[https://github.com/systemd/systemd/issues/31100 上流でサポートされていない]とされているので、避けるべきです。2つの回避策については [https://github.com/systemd/systemd/issues/15354#issuecomment-611077881 systemd issue 15354] を参照してください。
  +
  +
=== A520I および B550I マザーボードで PC がスリープから復帰しない ===
  +
  +
A520i および B550i チップセットを搭載した一部のマザーボードでは、システムが完全にスリープ状態に入らない、またはスリープ状態から復帰しないことがあります。症状は、システムがスリープ状態に入り、マザーボード上の内部 LED または電源 LED が点灯したまま、モニターの電源が切れるというものです。その後、システムはこの状態から復帰することができず、ハードパワーオフが必要となります。AMD で同様の問題が発生した場合、まずシステムが完全にアップデートされていることを確認し、AMD [[マイクロコード]] パッケージがインストールされているかどうかをチェックしてください。
  +
  +
{{ic|GPP0}} で始まる行のステータスが有効になっていることを確認します:
   
 
{{hc|$ cat /proc/acpi/wakeup|
 
{{hc|$ cat /proc/acpi/wakeup|
Device S-state Status Sysfs node
+
Device S-state Status Sysfs node
  +
GP12 S4 *enabled pci:0000:00:07.1
  +
GP13 S4 *enabled pci:0000:00:08.1
  +
XHC0 S4 *enabled pci:0000:0b:00.3
  +
GP30 S4 *disabled
  +
GP31 S4 *disabled
  +
PS2K S3 *disabled
  +
'''GPP0''' S4 '''*enabled''' pci:0000:00:01.1
  +
GPP8 S4 *enabled pci:0000:00:03.1
  +
PTXH S4 *enabled pci:0000:05:00.0
  +
PT20 S4 *disabled
  +
PT24 S4 *disabled
  +
PT26 S4 *disabled
  +
PT27 S4 *disabled
  +
PT28 S4 *enabled pci:0000:06:08.0
  +
PT29 S4 *enabled pci:0000:06:09.0
  +
}}
  +
  +
これが有効になっている場合は、次のコマンドを実行できます:
  +
  +
# echo GPP0 > /proc/acpi/wakeup
  +
  +
{{ic|systemctl suspend}} を実行してテストし、システムをスリープ状態にします。次に、数秒後にシステムを起動してみてください。うまくいく場合は、回避策を永続的にすることができます。systemd [[systemd#ユニットファイル|ユニットファイル]]を[[作成]]します。:
  +
  +
{{hc|/etc/systemd/system/toggle-gpp0-to-fix-wakeup.service|2=
  +
[Unit]
  +
Description="Disable GPP0 to fix suspend issue"
  +
  +
[Service]
  +
ExecStart=/bin/sh -c "/bin/echo GPP0 > /proc/acpi/wakeup"
  +
  +
[Install]
  +
WantedBy=multi-user.target
  +
}}
  +
  +
[[daemon-reload]] するか、新しく作成したユニットを[[起動/有効化]]してください。
  +
  +
あるいは、[[udev]] ルールを作成することもできます。先の例のように {{ic|GPP0}} の sysfs ノードが {{ic|pci:0000:00:01.1}} である場合、関連する情報は {{ic|udevadm info -a -p /sys/bus/pci/devices/0000\:00\:01.1}} を実行することで得られ、以下のような udev ルールを作成すれば良いことになります:
  +
  +
{{hc|/etc/udev/rules.d/10-gpp0-acpi-fix.rules|2=
  +
KERNEL=="0000:00:01.1", SUBSYSTEM=="pci", DRIVERS=="pcieport", ATTR{vendor}=="0x1022", ATTR{device}=="0x1483", ATTR{power/wakeup}="disabled"
  +
}}
  +
  +
デフォルトで、udev デーモンはシステム内の (ルールの) 変更を監視する用に設定されています。必要であれば、[[udev#新しいルールをロードする|手動でルールを再読み込み]]することもできます。
  +
  +
=== ノートパソコンをサスペンドする Fn キーが動作しない ===
  +
  +
{{ic|logind.conf}} をどう設定してもスリープボタンが動作しない場合 (ボタンを押しても syslog にメッセージすら表示されない)、おそらく logind がキーボードデバイスを監視していません。[https://lists.freedesktop.org/archives/systemd-devel/2015-February/028325.html] 次のコマンドを実行してください:
  +
  +
# journalctl --grep="Watching system buttons"
  +
  +
すると以下のような表示がされます:
  +
  +
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event2 (Power Button)
  +
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event3 (Sleep Button)
  +
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event4 (Video Bus)
  +
  +
キーボードデバイスが出力に無いことに注意してください。以下のようにして、キーボードデバイスを一覧表示してみてください:
  +
  +
{{hc|$ stat -c%N /dev/input/by-id/*-kbd|2=
 
...
 
...
  +
/dev/input/by-id/usb-SIGMACHIP_USB_Keyboard-event-kbd -> '''../event6'''
EHC1 S3 *enabled pci:0000:00:1d.0
 
EHC2 S3 *enabled pci:0000:00:1a.0
 
XHC S3 *enabled pci:0000:00:14.0
 
 
...
 
...
 
}}
 
}}
   
  +
次に、親キーボードデバイスの {{ic|ATTRS{name}<nowiki/>}} の値を調べます [https://systemd-devel.freedesktop.narkive.com/Rbi3rjNN/patch-1-2-logind-add-support-for-tps65217-power-button]。例えば、上記のコマンドの出力から、このキーボードデバイスのデバイス入力イベントは {{ic|'''event6'''}} であることがわかるので、このイベント名を使って {{ic|ATTRS{name}<nowiki/>}} 属性の値を検索することができます:
問題のデバイスは {{ic|EHC1}}, {{ic|EHC1}}, {{ic|XHC}} (USB 3.0) です。状態を変更するには root でデバイス名をファイルに echo してください:
 
   
  +
{{hc|# udevadm info -a /dev/input/'''event6'''|2=
# echo EHC1 > /proc/acpi/wakeup
 
  +
...
# echo EHC2 > /proc/acpi/wakeup
 
  +
KERNEL=="event6"
# echo XHC > /proc/acpi/wakeup
 
  +
...
  +
ATTRS{name}=="SIGMACHIP USB Keyboard"
  +
}}
   
  +
カスタムの udev ルールを作成して、"power-switch" タグを追加してください:
上記のコマンドでサスペンドが再度機能するようになります。ただし、設定は一時的なものなので再起動するたびに設定し直す必要があります。自動化したい場合は [[systemd#ユニットファイル]]を見てください。詳しくは [https://bbs.archlinux.org/viewtopic.php?pid=1575617#p1575617 BBS スレッド] を参照。
 
   
  +
{{hc|/etc/udev/rules.d/70-power-switch-my.rules|2=
=== System does not power off when hibernating ===
 
  +
ACTION=="remove", GOTO="power_switch_my_end"
 
  +
SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="SIGMACHIP USB Keyboard", TAG+="power-switch"
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 {{ic|HibernateMode}} to {{ic|shutdown}} in {{man|5|sleep.conf.d}}:
 
  +
LABEL="power_switch_my_end"
 
{{hc|/etc/systemd/sleep.conf.d/hibernatemode.conf|2=
 
[Sleep]
 
HibernateMode=shutdown
 
 
}}
 
}}
  +
 
  +
[[udev#新しいルールをロードする|上記の udev ルールを再読み込み]]して {{ic|systemd-logind.service}} を[[再起動]]したら、''logind'' の journal に {{ic|Watching system buttons on /dev/input/event6}} という出力が現れるはずです。
With the above configuration, if everything else is set up correctly, on invocation of a {{ic|systemctl hibernate}} the machine will shutdown saving state to disk as it does so.
 
  +
  +
{{TranslationStatus|Power management/Suspend and hibernate|2024-03-11|802809}}

2024年3月11日 (月) 16:24時点における最新版

関連記事

サスペンドの複数の方法を利用できます。とりわけ:

Suspend to idle
Intel は S0ix と呼んでおり、Microsoft は Modern Standby (以前は "Connected Standby") と呼んでいます。Linux カーネルでは S2Idle と呼ばれています。サポートされているシステムにおいて S3 スリープ状態の代わりに使用されるように設計されており、同等の節電機能を提供しますが、復帰に掛かる時間が大幅に短縮されます。
ヒント: WindowsmacOS はネットワーク活動のためにこの状態のデバイスの復帰をサポートしているので、これらの OS においてこの状態はバッテリーの消耗問題の影響を受けます。一方、Linux のソフトウェアエコシステムは現在この機能を使用しないため、影響を受けないはずです。
Suspend to RAM (サスペンド、スリープとも呼ばれます)
ACPI で S3 スリープ状態として定義されています。RAM を除くマシンのほとんど全てのパーツの電源を切ります。RAM への電源はマシンの状態を保存するために必要です。電力を多く節約できるので、ラップトップでは、バッテリーでコンピュータが稼働していてフタが閉じられた時 (もしくはユーザーが長い間操作しなかった時) は自動的にこのモードに移行するのが得策でしょう。
Suspend to disk (ハイバネートとも呼ばれます)
ACPI で S4 スリープ状態として定義されています。マシンの状態をスワップ領域に保存してマシンの電源を完全にオフにします。マシンに電源を入れた時、状態が復元されます。それまでは、電力消費量はゼロです。
Hybrid suspend (ハイブリットスリープとも呼ばれます)
サスペンドとハイバネートのハイブリッドです。Suspend to both と呼ばれることもあります。マシンの状態をスワップ領域に保存しますが、マシンの電源を切りません。代わりに、デフォルトのサスペンドを呼び出します。これによって、バッテリーを使いきっても、システムは即座に復帰できます。バッテリーが枯渇した時は、システムはディスクから復帰し、RAM からの復帰に比べて時間がかかりますが、システムの状態が失われることはありません。

カーネルは、基本的な機能を提供しており、問題のあるハードウェアドライバ/カーネルモジュール (例: ビデオカードの再初期化) に対処する機能を提供する高レベルなインターフェイスもいくつかあります。

目次

カーネルのインターフェイス (swsusp)

ノート: カーネルのインターフェイスを直接使用することは可能です (ユーザー空間で追加の処理が無いので高速です) が、高レベルインターフェイスを使用することが推奨されます。このインターフェイスは、追加の安全性チェックを行い、さらに、ハードウェアクロックの修正や無線ネットワークの回復などをするためのサスペンド前後のフック機構を提供しているので、より優れています。

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

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

高レベルインターフェイス (systemd)

ノート: 高レベルなインターフェイスの目的は、サスペンド/ハイバネートを行う際に利用できるバイナリ/スクリプトと、追加の準備/クリーンアップの作業を行うためのフックを実行する手段を提供することです。電源ボタンの押下、メニューのクリック、ノート PC の蓋イベントのときにスリープ状態に自動的に移行する方法については、電源管理#電源管理 を見てください。

systemd は、サスペンド、ハイバネート、ハイブリッドサスペンドを行うためのネイティブなコマンドを提供しています。これは、Arch Linux で使用されるデフォルトのインターフェイスです。

systemctl suspend は、特に設定せずとも動くはずです。systemctl hibernate に関しては、#ハイバネーション の手順に従わないと動作しないかもしれません。

また、サスペンドとハイバネートを組み合わせたようなモードが2つあります:

  • systemctl hybrid-sleep は、システムを RAM とディスクの両方にサスペンドします。なので、電源が完全に失われても、データ損失が発生しません。このモードは suspend to both とも呼ばれています。
  • systemctl suspend-then-hibernate は、最初は可能な限り長くシステムを RAM にサスペンドし、RTC アラームで復帰し、そしてハイバネートします。RTC アラームは systemd-sleep.conf(5) 内の HibernateDelaySec で設定します。デフォルトの値は、システムのバッテリーレベルが 5% に下がるまでの推定された時間に設定されます。システムにバッテリーが存在しない場合は、デフォルトで2時間に設定されます。推定時間は、systemd-sleep.conf(5) 内の SuspendEstimationSec によって指定された時間後のバッテリーレベルの変化から計算されます。SuspendEstimationSec の時間後、システムは短い間サスペンドから復帰し、計測を行います (システムが手動でサスペンドから復帰された場合も、計測が行われます)。

サスペンド/ハイバネートのフックの設定に関するその他の情報は、#スリープフック を見てください。また、systemctl(1)systemd-sleep(8)systemd.special(7) も参照してください。

サスペンドの方法を変更する

S0ix サスペンドが通常の S3 スリープと同じ節電機能を提供しないシステム、あるいは、電力を節約することが復帰を高速化することよりも優先される場合においては、デフォルトのサスペンド方法を変更することが可能です。

ヒント: S0ix は S3 スリープと同等かより高い節電性能を提供するはずです。意図通りに S0ix を機能させることができるかどうかは、次の Intel のブログ投稿を参照してください: How to achieve S0ix states in LinuxLinux S0ix TroubleshootingIdling Efficiently on Linux: A Case Study。Intel システムでは S0ixSelftestTool を使うことができます。

以下のコマンドは、ハードウェアによってサポートされていると広告されている全てのサスペンド方法を出力します (現在のサスペンド方法は角括弧に囲まれます[1]):

$ cat /sys/power/mem_sleep
[s2idle] shallow deep

ハードウェアが deep スリープ状態を広告していない場合、UEFI にそのような設定がないか確認してください。通常、PowerSleep state などのような項目にあります。S0ix のオプションは Windows 10Windows and LinuxS3/Modern standby support という名前です。S3 スリープのオプションは LegacyLinuxLinux S3S3 enabled という名前です。設定できない場合、s2idle を使い続けることもできます、ハイバネート を使うことを検討するか、DSDT テーブルにパッチを当ててみてください (あるいは、パッチ適用済みのバージョンを見つけてください)。

ノート: 最後の解決策は将来的に問題が発生する可能性があります。Windows を同梱しているシステムではデフォルトで "Modern standby" を使うよう推奨されているため、メーカーは ACPI S3 状態のバグの修正を停止しています。メーカーが自発的にそれを広告していない場合、おそらく、S3 状態は何らかの形で壊れています。

スリープの方法を変更したあと、スリープサイクルを何回かテストして、ハードウェアが S3 スリープで問題を起こさないかテストしてください:

# echo "deep" > /sys/power/mem_sleep

問題が無ければ、mem_sleep_default=deep カーネルパラメータ を使って変更を永続化できます。

いくつかの逆の状況では、問題のあるファームウェアが s2idle しかサポートしていないにも関わらず、deep をサポートしていると広告することがあります。この場合、sleep.conf.d(5) 内で SuspendState を使うことにより、s2idle を使うことができます:

/etc/systemd/sleep.conf.d/freeze.conf
[Sleep]
SuspendState=freeze

ハイバネーション

ハイバネートを行うには、次のことを行う必要があります: スワップパーティションかスワップファイルの作成する。初期ユーザー空間で復帰プロセスを初期化できるようにするために initramfs を設定する。Initramfs から利用できる方法でスワップ領域の場所を指定する (例えば、HibernateLocation EFI 変数を systemd で定義したり、resume= カーネルパラメータを設定したり)。これらの3つの手順は以下で詳細に説明されています。

ノート:
  • ディスク暗号化を利用する場合はdm-crypt/スワップの暗号化#suspend-to-disk を使用するを見てください。
  • linux-hardenedはハイバネーションをサポートしていません。詳しくはFS#63648を見てください。
  • zram 上のスワップへのハイバネートはサポートされていません。たとえ zram が永久記憶装置上のバッキングデバイスを使うように設定されていたとしてもです。logind は、zram 上のスワップ領域へハイバネートしようとする試みから保護します。

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

スワップパーティションが RAM より小さかったとしても、ハイバネートが成功する可能性は高いと思われます。image_size sysfs(5) 疑似ファイルに関する情報は カーネルドキュメントの "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つのスワップパーティション/スワップファイルに収まらなければなりません。[2]

initramfs の設定

  • Busybox ベースの initramfs を使用している場合 (Arch ではデフォルトです)、/etc/mkinitcpio.confresume フックを追加する必要があります。ラベルあるいは UUID どちらを使用している場合でもスワップパーティションは udev デバイスノードによって参照されるので、resume フックは udev フックのに追加する必要があります。デフォルトのフック設定に resume フックを追加すると以下のようになります:
HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block filesystems resume fsck)
変更を適用するために initramfs の再生成を忘れずに行ってください。
ノート: スワップ領域にスタックされたストレージ (例えば、dm-cryptRAIDLVM) を使用している場合は、最後のマッピングされるデバイスが、初期ユーザー空間内及び復帰プロセスの初期化前に利用できるようにする必要があります。つまり、どうすればよいかというと、resume フックを encryptlvm2 などのフックより後に置く必要があります (そのような環境である場合)。
  • initramfs で systemd フックを使っている場合は、復帰機構が既に提供されているので、フックを追加する必要はありません。

ハイバネート先指定を initramfs に渡す

システムがハイバネートする際、メモリイメージがスワップ領域に保存されます (メモリイメージには、マウント済みファイルシステムの状態も含まれます)。そのため、ハイバネートから復帰できるようにするには、ハイバネート先がどこであるかという情報が、initramfs で (つまり、ルートファイルシステムがマウントされる前の時点で) 利用できるようにする必要があります。

systemd v255 及び mkinitcpio v38 からは、システムが UEFI 上で実行されている場合、systemd-sleep(8) はハイバネート先として適切なスワップ領域を自動的に選択し、使用されたスワップ領域の情報は HibernateLocation EFI 変数に格納されます。次回のブート時には、systemd-hibernate-resume(8) がこの EFI 変数からスワップ領域の場所を読み込み、システムが復帰します。よって、システムがレガシー BIOS を使用している場合や、あなたが自動的に選択されるスワップ領域とは別のスワップ領域を使用したい場合を除いて、以下の手順は必須ではありません。

ハイバネート先を手動で指定する

カーネルパラメータ resume=swap_device を使用することで可能です。swap_device永続的なブロックデバイスの命名に従います。例えば:

  • resume=/dev/sda1
  • resume=UUID=4209c845-f495-4c43-8a03-5363dd433153
  • resume=/dev/mapper/archVolumeGroup-archLogicVolume – スワップが LVM 論理ボリューム上にある場合 (UUID や Label も使えるはずです)

カーネルパラメータは再起動後に有効となります。すぐにハイバネートできるようにするには、lsblk を使ってボリュームのメジャーデバイスナンバーとマイナーデバイスナンバーを手に入れて、/sys/power/resumemajor:minor という形式で書き込んでください。

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

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

スワップファイルを使用する場合、これに加えて #スワップファイルのオフセットを手に入れる の手順も行ってください。

スワップファイルのオフセットを手に入れる

スワップファイルをハイバネート用に使用する場合は、(スワップファイルが存在している) ファイルシステムを含んでいるブロックデバイスを resume= で指定する必要があり、さらに、スワップファイルの物理オフセットも resume_offset= カーネルパラメータで指定する必要があります。[3]

Btrfs 以外のファイルシステムでは、resume_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
...

この例では、resume_offset= の値は最初の 38912 になります。

あるいは、オフセットの値を直接手に入れるには:

# filefrag -v swap_file | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'

Btrfs の場合、filefrag ツールは使わないでください。filefrag から得られる "physical" オフセットの値は、ディスク上の実際の物理オフセットとは異なるからです。複数のデバイスをサポートするために、仮想的なディスクアドレス空間が存在するのです。[4] 代わりに、btrfs-inspect-internal(8) コマンドを使ってください。例えば:

# btrfs inspect-internal map-swapfile -r swap_file
198122980

この例では、カーネルパラメータは resume_offset=198122980 となります。

再起動せずにこの変更を即座に適用するには、resume offset を /sys/power/resume_offset に書き込んでください。例えば、オフセットが 38912 である場合は:

# echo 38912 > /sys/power/resume_offset
ヒント: 次のコマンドは、スワップファイルのバッキングデバイスを特定する際に使用できます: findmnt -no UUID -T swap_file
ノート: 暗号化コンテナ (LUKS)、 RAID、 LVM のようなスタックブロックデバイスでは、resume パラメータはスワップファイルのあるファイルシステムを含んでいる、アンロックまたはマップされたデバイスを指していなければなりません。

ハイバネート用のスワップファイルを zram で保持する

ヒント: 以下の方法は複数のスワップ領域を使用しますが、zswap を使えば似たようなことをすることができます。

RAM 圧縮 (zram) でのハイバーネートの問題は、複数のスワップ領域を同時に保持することで解決できます。Systemd は、ハイバネートをトリガーする前に zram ブロックデバイスを常に無視するので、特に設定せずに両方の領域 (スワップファイルと zram) を保持できるはずです。

スワップファイルの設定が済んだら、zram のページの手順に従ってください。このとき、zram に高いスワップ優先度 (例えば pri=100) を割り当ててください。

ノート:

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 オプション。 そうしないと、使用済みスペースの割り当てが解除されます。

スリープフック

カスタムの systemd ユニット

systemd は、スリープ状態に応じて suspend.targethibernate.targethybrid-sleep.targetsuspend-then-hibernate.target のどれかを開始します。これらの target は全て、sleep.target も開始します。これらの target はどれも、サスペンド/ハイバネートの前や後にカスタムのユニットを実行するために使用することができます。ユーザーのアクション用と root ユーザー/システムのアクション用とで、別々のファイルを作成する必要があります。例えば:

/etc/systemd/system/user-suspend@.service
[Unit]
Description=User suspend actions
Before=sleep.target

[Service]
User=%I
Type=forking
Environment=DISPLAY=:0
ExecStartPre= -/usr/bin/pkill -u %u unison ; /usr/local/bin/music.sh stop
ExecStart=/usr/bin/sflock
ExecStartPost=/usr/bin/sleep 1

[Install]
WantedBy=sleep.target
/etc/systemd/system/user-resume@.service
[Unit]
Description=User resume actions
After=suspend.target

[Service]
User=%I
Type=simple
ExecStart=/usr/local/bin/ssh-connect.sh

[Install]
WantedBy=suspend.target

変更を適用するには、user-suspend@user.serviceuser-resume@user.service を有効化してください。

ノート: スクリーンが"ロックされる"前にスクリーンロックが返ってきてしまい、サスペンドから復帰するときに画面が点滅することがあります。ExecStartPost=/usr/bin/sleep 1 で小さな遅延を追加することでこれを防止できます。

root ユーザー/システムのアクション用:

/etc/systemd/system/root-suspend.service
[Unit]
Description=Local system suspend actions
Before=sleep.target

[Service]
Type=simple
ExecStart=-/usr/bin/pkill sshfs

[Install]
WantedBy=sleep.target
/etc/systemd/system/root-resume.service
[Unit]
Description=Local system resume actions
After=suspend.target

[Service]
Type=simple
ExecStart=/usr/bin/systemctl restart mnt-media.automount

[Install]
WantedBy=suspend.target

スリープ/復帰のユニットの統合

サスペンド/レジュームのサービスファイルを統合すれば、様々なフェイズ (スリープ/レジューム) やターゲット (サスペンド/ハイバネート/ハイブリッドスリープ) でやることをひとつのフックで行うことができます。

例と説明:

/etc/systemd/system/wicd-sleep.service
[Unit]
Description=Wicd sleep hook
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-/usr/share/wicd/daemon/suspend.py
ExecStop=-/usr/share/wicd/daemon/autoconnect.py

[Install]
WantedBy=sleep.target
  • RemainAfterExit=yes: 起動後、明示的に止められるまでサービスは常時 active とみなされます。
  • StopWhenUnneeded=yes: active 時、他のサービスから必要とされなくなった場合、サービスは停止されます。この例では、sleep.target が停止されるとこのサービスは停止されます。
  • sleep.target では StopWhenUnneeded=yes が設定されているため、このフックは別のタスクにおいても適切に開始/停止することが保証されます。

/usr/lib/systemd/system-sleep のフック

ノート: systemd-sleep(8) によれば、この方法は systemd ではハックなやり方だとされています。systemd-sleep は、これらのフックを1つずつではなく並列に実行します。順序実行がサポートされている、より明確に定義されたインターフェイスについては、#カスタムの systemd ユニット をみてください。

systemd-sleep は、/usr/lib/systemd/system-sleep/ 内の全ての実行可能ファイルを実行します。このとき、2つの引数が渡されます:

  1. pre または post: マシンがスリープしようとしているのか、復帰しようとしているのか。
  2. suspendhibernatehybrid-sleep のどれか: どのスリープ状態が実行される/されたのか。

カスタムスクリプトの出力は、systemd-suspend.servicesystemd-hibernate.servicesystemd-hybrid-sleep.service によって記録されます。systemdjournalctl でこのログを見ることができます:

# journalctl -b -u systemd-suspend.service

カスタムのスリープスクリプト例:

/usr/lib/systemd/system-sleep/example.sh
#!/bin/sh
case $1/$2 in
  pre/*)
    echo "Going to $2..."
    ;;
  post/*)
    echo "Waking up from $2..."
    ;;
esac

スクリプトを実行可能にするのを忘れないで下さい。

ヒントとテクニック

スリープを完全に無効化する

デバイスをサーバなどとして使用している場合、サスペンドは必要ないかもしれませんし、かえって望ましくない可能性もあります。systemd-sleep.conf(5) を使えば任意のスリープ状態を無効化することができます:

/etc/systemd/sleep.conf.d/disable-suspend.conf
[Sleep]
AllowSuspend=no
AllowHibernation=no
AllowHybridSleep=no
AllowSuspendThenHibernate=no

Intel Rapid Start Technology (IRST)

Intel Rapid Start Technology とは、ハイバネートするためのハードウェア上の方法で、あらかじめ設定された時間の後やバッテリー状態に基づいてスリープからハイバネートに移行できるようにします。IRSTは、オペレーティングシステムのレベルではなくファームウェアによって行われるので、通常のハイバネートよりも速く信頼性が高いはずです。一般的に、IRST はファームウェアで有効化する必要があり、またファームウェアで、サスペンド/バッテリイベント後にハイバネートをトリガーするまでの時間を設定できます。しかし、一部のデバイスは IRST をファームウェアでサポートしていますが、Intel の Windows ドライバからでしか設定できません。そのような場合には、以下で説明している intel-rst カーネルモジュールで Linux でもイベントを設定できるはずです。

Intel Rapid Start Technology (IRST) が有効の場合、deep sleep からの再開には "S3から再開するよりも数秒長くなりますが、ハイバネートから再開するよりもはるかに高速です"。

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

警告: Intel Rapid Start パーティションは暗号化されていません。「Intel は、あなたがソフトウェアベースのディスク暗号化を使用している場合、Intel Rapid Start Technology を無効化することを推奨します。」[5]

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

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

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

Linux カーネルで IRST ハイバネートイベントを設定するには、CONFIG_INTEL_RST オプションでカーネルに組み込むか、カーネルモジュールとして利用可能である必要があります。modprobe intel_rst を実行してモジュールをロードすれば、/sys/bus/acpi/drivers/intel_rapid_start/*/ にファイル wakeup_eventswakeup_time が生成されるはずです。これらを用いて、さらなる設定を行うことができます。このモジュールは簡潔にドキュメント化されています。詳細は drivers/platform/x86/intel/rst.c を見てください。

Intel Rapid Start Technology に関する情報は、general Q&Auser guides も見てください。

トラブルシューティング

ACPI_OS_NAME

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

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

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

ハードウェアの watchdog タイマーを使用している場合に問題が起こることもあります (デフォルトで無効化されています、systemd-system.conf(5) § OPTIONSRuntimeWatchdogSec= を見てください)。バグのある watchdog タイマーにより、システムがハイバネートイメージの作成を終える前に、コンピュータがリセットされることがあります。

時々、initramfs 内からのデバイスの初期化によって黒画面が発生することがあります。Mkinitcpio#MODULES 内にあるモジュールを削除し、kms フックを削除し、initramfs を再ビルドすると、この問題を解決できる可能性があります (特に、KMS の早期開始が設定されたグラフィックスドライバの場合)。復帰前にそのようなデバイスを初期化すると、整合性がなくなり、システムのハイバネートからの復帰を妨げてしまう可能性があります。これは RAM からの復帰には影響しません。また、ブログ記事 best practices to debug suspend issues も確認してください。

ATI ビデオドライバから新しい AMDGPU ドライバに移行すると、ハイバネートと復帰のプロセスを成功させることができる可能性があります。

NVIDIA ユーザは、nvidiafb モジュールをブラックリスト化すると、問題が解決するかもしれません。[6]

Intel CPU を搭載していて、タッチパッドのために intel_lpss_pci をロードするノート PC では、復帰時にカーネルパニックを引き起こすことがあります(この時、caps lock が点滅する) [7]。このモジュールは、以下のように initramfs に追加する必要があります:

/etc/mkinitcpio.conf
MODULES=(... intel_lpss_pci ...)

そして、initramfs を再生成してください。

Wake-on-LAN

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

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

電源管理/復帰トリガー#サスペンドからすぐに復帰する を見てください。

AMD CPU 上で Linux カーネル 6.1 以上を使用している場合、これはカーネル内の S3 関連の制御ポリシーの問題が原因である可能性もあります。一時的な解決策は、関連する i2c デバイスの復帰をオフにすることです。関連する i2c デバイスは以下のコマンドで見つけられます:

$ ls /sys/bus/i2c/devices/*/power/wakeup

デバイス名の形式は i2c-ELAN0679:00i2c-MSFT0001:00 であるはずです。次に、以下のコマンドでサスペンドに移行できるかテストします:

# echo disabled > /sys/bus/i2c/devices/device_name/power/wakeup
# systemctl suspend

これでうまく行くならば、udev ルールを追加することで、この設定を永続化できます:

/etc/udev/rules.d/99-avoid-i2c-wakeup.rules
KERNEL=="device_name", SUBSYSTEM=="i2c", ATTR{power/wakeup}="disabled"

ハイバネートした時にシステムの電源が落ちない

システムをハイバネートした時には、(状態をディスク上に保存したあとに)システムの電源が落ちるはずです。時々、ハイバネートした後も電源 LED が光り続けることがあります。これが起こる場合、sleep.conf.d(5)HibernateModeshutdown に設定すると問題が解決するかもしれません。

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

上記の設定により、その他の設定が正しく行われていれば、systemctl hibernate を実行するとマシンがシャットダウンし、状態をディスクに保存します。

ハイバネート後に起動するとオペレーティングシステムが見つからない (または、間違った OS が起動する)

これは、ブートディスクが外部ディスクである場合に起こる可能性があります。BIOS/ファームウェアの制限が原因であるようです。ハイバネーションは外部 (あるいは別の) ディスク上の OS から行われたが、BIOS/ファームウェアは内部ディスクから起動を試みてしまっているのです。

#ハイバネートした時にシステムの電源が落ちない で説明したように HibernateMode=shutdown を設定することで、この問題を永久に解決できます。すでにシステムから締め出されてしまっている場合、システムを4回再起動 (毎回、エラーが表示されるまで待ってください) してみることで、一部の BIOS 上では通常のブート手順を強制することができます。

/home にスワップファイルを置く

スワップファイルが /home/ にある場合、systemd-logind はスワップファイルにアクセスできず、Call to Hibernate failed: No such file or directory という警告メッセージを出力して、systemctl hibernate の実行時に認証を求められます。このようなセットアップは、上流でサポートされていないとされているので、避けるべきです。2つの回避策については systemd issue 15354 を参照してください。

A520I および B550I マザーボードで PC がスリープから復帰しない

A520i および B550i チップセットを搭載した一部のマザーボードでは、システムが完全にスリープ状態に入らない、またはスリープ状態から復帰しないことがあります。症状は、システムがスリープ状態に入り、マザーボード上の内部 LED または電源 LED が点灯したまま、モニターの電源が切れるというものです。その後、システムはこの状態から復帰することができず、ハードパワーオフが必要となります。AMD で同様の問題が発生した場合、まずシステムが完全にアップデートされていることを確認し、AMD マイクロコード パッケージがインストールされているかどうかをチェックしてください。

GPP0 で始まる行のステータスが有効になっていることを確認します:

$ cat /proc/acpi/wakeup
Device	S-state	  Status   Sysfs node
GP12	  S4	*enabled   pci:0000:00:07.1
GP13	  S4	*enabled   pci:0000:00:08.1
XHC0	  S4	*enabled   pci:0000:0b:00.3
GP30	  S4	*disabled
GP31	  S4	*disabled
PS2K	  S3	*disabled
GPP0	  S4	*enabled   pci:0000:00:01.1
GPP8	  S4	*enabled   pci:0000:00:03.1
PTXH	  S4	*enabled   pci:0000:05:00.0
PT20	  S4	*disabled
PT24	  S4	*disabled
PT26	  S4	*disabled
PT27	  S4	*disabled
PT28	  S4	*enabled   pci:0000:06:08.0
PT29	  S4	*enabled   pci:0000:06:09.0

これが有効になっている場合は、次のコマンドを実行できます:

# echo GPP0 > /proc/acpi/wakeup

systemctl suspend を実行してテストし、システムをスリープ状態にします。次に、数秒後にシステムを起動してみてください。うまくいく場合は、回避策を永続的にすることができます。systemd ユニットファイル作成します。:

/etc/systemd/system/toggle-gpp0-to-fix-wakeup.service
[Unit]
Description="Disable GPP0 to fix suspend issue"

[Service]
ExecStart=/bin/sh -c "/bin/echo GPP0 > /proc/acpi/wakeup"

[Install]
WantedBy=multi-user.target

daemon-reload するか、新しく作成したユニットを起動/有効化してください。

あるいは、udev ルールを作成することもできます。先の例のように GPP0 の sysfs ノードが pci:0000:00:01.1 である場合、関連する情報は udevadm info -a -p /sys/bus/pci/devices/0000\:00\:01.1 を実行することで得られ、以下のような udev ルールを作成すれば良いことになります:

/etc/udev/rules.d/10-gpp0-acpi-fix.rules
KERNEL=="0000:00:01.1", SUBSYSTEM=="pci", DRIVERS=="pcieport", ATTR{vendor}=="0x1022", ATTR{device}=="0x1483", ATTR{power/wakeup}="disabled"

デフォルトで、udev デーモンはシステム内の (ルールの) 変更を監視する用に設定されています。必要であれば、手動でルールを再読み込みすることもできます。

ノートパソコンをサスペンドする Fn キーが動作しない

logind.conf をどう設定してもスリープボタンが動作しない場合 (ボタンを押しても syslog にメッセージすら表示されない)、おそらく logind がキーボードデバイスを監視していません。[8] 次のコマンドを実行してください:

# journalctl --grep="Watching system buttons"

すると以下のような表示がされます:

May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event2 (Power Button)
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event3 (Sleep Button)
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event4 (Video Bus)

キーボードデバイスが出力に無いことに注意してください。以下のようにして、キーボードデバイスを一覧表示してみてください:

$ stat -c%N /dev/input/by-id/*-kbd
...
/dev/input/by-id/usb-SIGMACHIP_USB_Keyboard-event-kbd -> ../event6
...

次に、親キーボードデバイスの ATTRS{name} の値を調べます [9]。例えば、上記のコマンドの出力から、このキーボードデバイスのデバイス入力イベントは event6 であることがわかるので、このイベント名を使って ATTRS{name} 属性の値を検索することができます:

# udevadm info -a /dev/input/event6
...
KERNEL=="event6"
...
ATTRS{name}=="SIGMACHIP USB Keyboard"

カスタムの udev ルールを作成して、"power-switch" タグを追加してください:

/etc/udev/rules.d/70-power-switch-my.rules
ACTION=="remove", GOTO="power_switch_my_end"
SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="SIGMACHIP USB Keyboard", TAG+="power-switch"
LABEL="power_switch_my_end"

上記の udev ルールを再読み込みして systemd-logind.service再起動したら、logind の journal に Watching system buttons on /dev/input/event6 という出力が現れるはずです。

翻訳ステータス: このページは en:Power management/Suspend and hibernate の翻訳バージョンです。最後の翻訳日は 2024-03-11 です。もし英語版に 変更 があれば、翻訳の同期を手伝うことができます。