「電源管理/サスペンドとハイバネート」の版間の差分
(同期) |
(同期) |
||
(5人の利用者による、間の58版が非表示) | |||
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 の蓋イベントのときにスリープ状態に自動的に移行する方法については、[[電源管理#ACPI イベント]] を見てください。}} |
||
− | 詳しくは [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'' とも呼ばれています。 |
||
− | === tuxonice === |
||
+ | * {{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}} も参照してください。 |
|
+ | == サスペンドの方法を変更する == |
||
− | [[TuxOnIce]] の記事を参照してください。 |
||
+ | S0ix サスペンドが通常の S3 スリープと同じ節電機能を提供しないシステム、あるいは、電力を節約することが復帰を高速化することよりも優先される場合においては、デフォルトのサスペンド方法を変更することが可能です。 |
||
− | == 高レベルインターフェイス == |
||
+ | {{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] を使うことができます。}} |
||
− | {{Note|これらのパッケージではサスペンド・ハイバネートを行うためのバイナリ・スクリプトを提供します。実際に電源ボタンやメニュークリック、ラップトップのカバーのイベントなどと結びつけるのは他のツールで行うのが通常です。(ラップトップのカバーが閉じられたり、バッテリーが枯渇するなど)特定の電源イベントで自動的にサスペンド・ハイバネートをするには、[[Acpid]] の実行について調べて下さい。}} |
||
+ | 以下のコマンドは、ハードウェアによってサポートされていると広告されている全てのサスペンド方法を出力します (現在のサスペンド方法は角括弧に囲まれます[https://docs.kernel.org/admin-guide/pm/sleep-states.html#basic-sysfs-interfaces-for-system-suspend-and-hibernation]): |
||
− | === systemd === |
||
+ | {{hc|$ cat /sys/power/mem_sleep| |
||
− | [[systemd]] はサスペンド・ハイバネート・ハイブリッドサスペンドを行うためのネイティブのコマンドを提供しています。詳しくは [[電源管理#systemd による電源管理]] を見て下さい。これは Arch Linux で使われているデフォルトのインターフェースです。 |
||
+ | [s2idle] shallow deep |
||
+ | }} |
||
+ | {| class="wikitable sortable" |
||
− | サスペンド・ハイバネートのフックの設定に関する情報は[[電源管理#スリープフック]]に載っています。{{ic|man systemctl}}, {{ic|man systemd-sleep}}, {{ic|man systemd.special}} もあわせて参照してください。 |
||
+ | |+ mem_sleep でサポートされているスリープ状態 |
||
+ | |- |
||
+ | ! mem_sleep 文字列 !! スリープ状態 |
||
+ | |- |
||
+ | | s2idle || [https://docs.kernel.org/admin-guide/pm/sleep-states.html#suspend-to-idle suspend-to-idle] |
||
+ | |- |
||
+ | | shallow || [https://docs.kernel.org/admin-guide/pm/sleep-states.html#standby standby] |
||
+ | |- |
||
+ | | deep || [https://docs.kernel.org/admin-guide/pm/sleep-states.html#suspend-to-ram suspend-to-RAM] |
||
+ | |} |
||
+ | ハードウェアが {{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]] テーブルにパッチを当ててみてください (あるいは、パッチ適用済みのバージョンを見つけてください)。 |
||
− | === pm-utils === |
||
+ | {{Note|最後の解決策は将来的に問題が発生する可能性があります。Windows を同梱しているシステムではデフォルトで "Modern standby" を使うよう推奨されているため、メーカーは ACPI S3 状態のバグの修正を停止しています。メーカーが自発的にそれを広告していない場合、おそらく、S3 状態は何らかの形で壊れています。}} |
||
− | pm-utils はバックエンドのサスペンド・ハイバネート機能をカプセル化するシェルスクリプトのセットです。サスペンドの前後に行う設定やプロセスをカスタマイズするための様々なフックも入っています。 |
||
+ | スリープの方法を変更したあと、スリープサイクルを何回かテストして、ハードウェアが S3 スリープで問題を起こさないかテストしてください: |
||
− | [[pm-utils]] の記事を参照してください。 |
||
+ | |||
+ | # echo deep > /sys/power/mem_sleep |
||
+ | |||
+ | 問題が無ければ、{{ic|1=mem_sleep_default=deep}} [[カーネルパラメータ]] か、もしくは {{man|5|systemd-sleep.conf}} の {{ic|MemorySleepMode}} ディレクティブで変更を永続化することができます: |
||
+ | |||
+ | {{hc|/etc/systemd/sleep.conf.d/mem-deep.conf|2= |
||
+ | [Sleep] |
||
+ | MemorySleepMode=deep |
||
+ | }} |
||
+ | |||
+ | いくつかの逆の状況では、問題のあるファームウェアが {{ic|s2idle}} しかサポートしていないにも関わらず、{{ic|deep}} をサポートしていると広告することがあります。この場合、{{ic|SuspendState}} 設定を使うことにより、{{ic|s2idle}} を使うことができます: |
||
+ | |||
+ | {{hc|/etc/systemd/sleep.conf.d/freeze.conf|2= |
||
+ | [Sleep] |
||
+ | SuspendState=freeze |
||
+ | }} |
||
== ハイバネーション == |
== ハイバネーション == |
||
− | ハイバネー |
+ | ハイバネートを行うには、次のことを行う必要があります: [[スワップ]]パーティションかスワップファイルの作成する。初期ユーザー空間で復帰プロセスを初期化できるようにするために [[#initramfs の設定|initramfs を設定する]]。Initramfs から利用できる方法でスワップ領域の場所を指定する (例えば、{{ic|HibernateLocation}} EFI 変数を [[systemd]] で定義したり、{{ic|1=resume=}} [[カーネルパラメータ]]を設定したり)。これらの3つの手順は以下で詳細に説明されています。 |
+ | |||
+ | {{Note| |
||
+ | * [[ディスク暗号化]]を利用する場合は[[dm-crypt/スワップの暗号化#suspend-to-disk を使用する]]を見てください。 |
||
+ | * {{Pkg|linux-hardened}}はハイバネーションをサポートしていません。詳しくは{{Bug|63648}}を見てください。 |
||
+ | * zram 上のスワップへのハイバネートはサポートされていません。たとえ zram が永久記憶装置上のバッキングデバイスを使うように設定されていたとしてもです。''logind'' は zram 上のスワップ領域へのハイバネートから保護してくれますが、スワップ領域を複数作っておくという方法もあります。メモリはスワップファイルに保存され、他の利用可能なスワップ領域は zram 用に予約されます。詳細は [[#ハイバネート用のスワップファイルを zram で保持する]] を見てください。 |
||
+ | }} |
||
=== スワップパーティション(ファイル)のサイズについて === |
=== スワップパーティション(ファイル)のサイズについて === |
||
− | スワップパーティションが RAM より小さかったとしても、ハイバネートが成功する可能性は高いと思われます。[https:// |
+ | スワップパーティションが 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 - 一時ファイル]] を使うことができます: |
||
− | : ''{{ic|/sys/power/image_size}} は suspend-to-disk によって作成されるイメージのサイズを制御します。イメージサイズの上限として使われる負ではない整数 (バイト) を示す文字列で書くことが出来ます。suspend-to-disk はイメージサイズがその数字を超えないように出来る限りのことをします。ただし、それが無理だということがわかったら、とにかく出来る限り小さいイメージを使ってサスペンドを試みます。特に、このファイルに "0" と書かれていた場合、サスペンドのイメージは目一杯小さくなります。このファイルを読むと現在のイメージのサイズ制限が表示され、デフォルトでは利用可能な RAM の2/5に設定されています。'' |
||
+ | {{hc|/etc/tmpfiles.d/hibernation_image_size.conf| |
||
− | (スワップパーティションを小さくして) {{ic|/sys/power/image_size}} の値を減らしてサスペンドのイメージを出来る限り小さくすることも、値を増やしてハイバネーションを高速化することも可能です。 |
||
+ | # 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 microcode 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 に渡す === |
||
+ | |||
+ | システムがハイバネートする際、メモリイメージがスワップ領域に保存されます (メモリイメージには、マウント済みファイルシステムの状態も含まれます)。そのため、ハイバネートから復帰できるようにするには、ハイバネート先がどこであるかという情報が、initramfs で (つまり、ルートファイルシステムがマウントされる前の時点で) 利用できるようにする必要があります。 |
||
+ | |||
+ | {{Pkg|systemd}} v255 及び {{Pkg|mkinitcpio}} v38 からは、システムが [[UEFI]] 上で実行されている場合、{{man|8|systemd-sleep}} はハイバネート先として適切なスワップ領域を自動的に選択し、使用されたスワップ領域の情報は {{ic|HibernateLocation}} EFI 変数に格納されます。次回のブート時には、{{man|8|systemd-hibernate-resume}} がこの EFI 変数からスワップ領域の場所を読み込み、システムが復帰します。よって、システムがレガシー [[Arch ブートプロセス#BIOS|BIOS]] を使用している場合や、あなたが自動的に選択されるスワップ領域とは別のスワップ領域を使用したい場合を除いて、以下の手順は必須ではありません。 |
||
+ | ==== ハイバネート先を手動で指定する ==== |
||
− | === 必要なカーネルパラメータ === |
||
− | カーネルパラメータ {{ic|1=resume='' |
+ | [[カーネルパラメータ]] {{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}} |
+ | * {{ic|1=resume=/dev/mapper/archVolumeGroup-archLogicVolume}} – スワップが [[LVM]] 論理ボリューム上にある場合 (UUID や Label も使えるはずです) |
+ | [[カーネルパラメータ]]は再起動後に有効となります。すぐにハイバネートできるようにするには、[[lsblk]] を使ってボリュームのメジャーデバイスナンバーとマイナーデバイスナンバーを手に入れて、{{ic|/sys/power/resume}} に {{ic|''major'':''minor''}} という形式で書き込んでください。 |
||
− | {{ic|resume}} パラメータで使用する命名法は基本的に {{ic|root}} パラメータで使用する命名法と同じにしてください。 |
||
+ | 例えば、スワップデバイスが {{ic|8:3}} の場合: |
||
− | 設定は使用している[[ブートローダー]]によって異なります。詳しくは[[カーネルパラメータ]]を参照してください。 |
||
+ | # echo 8:3 > /sys/power/resume |
||
− | ==== スワップファイルにハイバネーション ==== |
||
+ | スワップファイルを使用する場合、これに加えて [[#スワップファイルのオフセットを手に入れる]] の手順も行ってください。 |
||
− | {{Warning|[[Btrfs#スワップファイル|Btrfs]] はスワップファイルをサポートしていません。この警告に従わない場合、ファイルシステムが破損するおそれがあります。ループデバイスを経由してマウントしているときに Btrfs でスワップファイルを使うと、スワップパフォーマンスが著しく低下してしまいます。}} |
||
+ | ===== スワップファイルのオフセットを手に入れる ===== |
||
− | スワップパーティションの代わりにスワップファイルを使うには追加のカーネルパラメータ {{ic|1=resume_offset=''swap_file_offset''}} が必要です。 |
||
+ | [[スワップファイル]]をハイバネート用に使用する場合は、(スワップファイルが存在している) ファイルシステムを含んでいるブロックデバイスを {{ic|1=resume=}} で指定する必要があり、さらに、スワップファイルの物理オフセットも {{ic|1=resume_offset=}} [[カーネルパラメータ]]で指定する必要があります。[https://docs.kernel.org/power/swsusp-and-swap-files.html] |
||
− | {{ic|''swap_file_offset''}} の値は {{ic|filefrag -v ''swap_file''}} を実行することで取得できます。テーブル形式で出力され、必要な値は {{ic|physical_offset}} カラムの一番上の段にあります。例えば: |
||
+ | |||
− | {{hc|# filefrag -v /swapfile|<nowiki> |
||
+ | [[Btrfs]] 以外のファイルシステムでは、{{ic|1=resume_offset=}} の値は {{ic|filefrag -v ''swap_file''}} を実行することで得られます。このコマンドは表を出力します。必要な値は {{ic|physical_offset}} 列の最初の行にあります。 |
||
+ | |||
+ | 例えば: |
||
+ | |||
+ | {{hc|# filefrag -v /swapfile| |
||
Filesystem type is: ef53 |
Filesystem type is: ef53 |
||
File size of /swapfile is 4294967296 (1048576 blocks of 4096 bytes) |
File size of /swapfile is 4294967296 (1048576 blocks of 4096 bytes) |
||
ext: logical_offset: physical_offset: length: expected: flags: |
ext: logical_offset: physical_offset: length: expected: flags: |
||
− | 0: 0.. 0: 38912.. 38912: 1: |
+ | 0: 0.. 0: '''38912'''.. 38912: 1: |
1: 1.. 22527: 38913.. 61439: 22527: unwritten |
1: 1.. 22527: 38913.. 61439: 22527: unwritten |
||
2: 22528.. 53247: 899072.. 929791: 30720: 61440: unwritten |
2: 22528.. 53247: 899072.. 929791: 30720: 61440: unwritten |
||
... |
... |
||
+ | }} |
||
− | </nowiki>}} |
||
+ | |||
+ | この例では、{{ic|1=resume_offset=}} の値は最初の {{ic|38912}} になります。 |
||
+ | |||
+ | あるいは、オフセットの値を直接手に入れるには: |
||
+ | |||
+ | # filefrag -v ''swap_file'' | awk '$1=="0:" {print substr($4, 1, length($4)-2)}' |
||
+ | |||
+ | [[Btrfs]] の場合、''filefrag'' ツールは使わないでください。''filefrag'' から得られる "physical" オフセットの値は、ディスク上の実際の物理オフセットとは異なるからです。複数のデバイスをサポートするために、仮想的なディスクアドレス空間が存在するのです。[https://bugzilla.kernel.org/show_bug.cgi?id=202803] 代わりに、{{man|8|btrfs-inspect-internal}} コマンドを使ってください。例えば: |
||
+ | |||
+ | {{hc|# btrfs inspect-internal map-swapfile -r ''swap_file''| |
||
+ | 198122980 |
||
+ | }} |
||
+ | |||
+ | この例では、カーネルパラメータは {{ic|1=resume_offset=198122980}} となります。 |
||
+ | |||
+ | 再起動せずにこの変更を即座に適用するには、resume offset を {{ic|/sys/power/resume_offset}} に書き込んでください。例えば、オフセットが {{ic|38912}} である場合は: |
||
+ | |||
+ | # echo 38912 > /sys/power/resume_offset |
||
+ | |||
+ | {{Tip|次のコマンドは、スワップファイルのバッキングデバイスを特定する際に使用できます: {{ic|1=findmnt -no UUID -T ''swap_file''}}}} |
||
+ | |||
+ | {{Note|暗号化コンテナ (LUKS)、 RAID、 LVM のようなスタックブロックデバイスでは、{{ic|resume}} パラメータはスワップファイルのあるファイルシステムを含んでいる、アンロックまたはマップされたデバイスを指していなければなりません。}} |
||
+ | |||
+ | === ハイバネート用のスワップファイルを zram で保持する === |
||
+ | |||
+ | {{Tip|以下の方法は複数のスワップ領域を使用しますが、[[zswap]] を使えば似たようなことをすることができます。}} |
||
+ | RAM 圧縮 (zram) でのハイバーネートの問題は、複数のスワップ領域を同時に保持することで解決できます。[[Systemd]] は、ハイバネートをトリガーする前に zram ブロックデバイスを常に無視するので、特に設定せずに両方の領域 (スワップファイルと zram) を保持できるはずです。 |
||
− | この例では {{ic|''swap_file_offset''}} の値は2つのピリオドが付いている最初の {{ic|38912}} です。 |
||
+ | [[#スワップファイルのオフセットを手に入れる|スワップファイルの設定]]が済んだら、[[zram]] のページの手順に従ってください。このとき、zram に'''高いスワップ優先度''' (例えば {{ic|1=pri=100}}) を割り当ててください。 |
||
− | {{ic|''swap_file_offset''}} の値は {{ic|swap-offset ''swap_file''}} でも取得することができます。''swap-offset'' バイナリは {{AUR|uswsusp-git}} パッケージに含まれています。 |
||
{{Note| |
{{Note| |
||
+ | * ハイバネート用のオンデマンドのスワップユニットは作成'''しないでください'''。これは公式にはサポートされていません。Systemd の issue [https://github.com/systemd/systemd/issues/16708 #16708] と [https://github.com/systemd/systemd/issues/30083 #30083] を参照してください。 |
||
− | * カーネルパラメータ {{ic|resume}} にはスワップファイル自体ではなく、スワップファイルが含まれているパーティションのデバイスを指定する必要があることに注意してください。カーネルパラメータ {{ic|resume_offset}} は resume デバイス上に存在するスワップファイルの開始位置を示しています。カーネルパラメータを有効化するために、ハイバネーションをする前に再起動が必要です。 |
||
+ | * カーネルは無名 (anonymous) ページの回収とスワップを行います。スワップ領域を利用しないと、メモリ使用効率の悪化につながる可能性があります。ユーザーは、{{ic|memory.low}} によって特定のアプリケーションにおけるメモリ回収の優先度を管理することができます (これは[[コントロールグループ]]で調整可能です)。全体として、この方が [[swappiness]] パラメータを設定するよりも効率的です。 |
||
− | * [[uswsusp]] を使う場合、{{ic|resume device}} キーと {{ic|resume offset}} キーを使って {{ic|/etc/suspend.conf}} に上記2つのパラメータを記述してください。この場合再起動は必要ありません。 |
||
+ | * 詳細は[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 ボリュームへのハイバネーション === |
||
− | {{Tip|スワップファイルを作成する目的が、仮想メモリの拡張ではなくハイバネートがしたいだけの場合、スワップファイルの [[スワップ#Swappiness|Swappiness]] を減らすとよいでしょう。}} |
||
+ | thinly-provisioned [[LVM]] されたボリュームへの休止状態は可能ですが、ボリュームが完全に割り当てられていることを確認する必要があります。そうしないと、再開に失敗します。{{Bug|50703}} を見てください。 |
||
− | === initramfs の設定 === |
||
+ | LVM ボリュームをゼロで埋めるだけで、 LVM ボリュームを完全に割り当てることができます。 例えば: |
||
− | * [[initramfs]] で {{ic|base}} フックを使っている場合 (Arch ではデフォルトで使っています)、{{ic|/etc/mkinitcpio.conf}} に {{ic|resume}} フックを追加する必要があります。ラベルあるいは UUID どちらを使用している場合でもスワップパーティションは udev デバイスノードによって参照されるので、{{ic|resume}} フックは必ず {{ic|filesystems}} の前に追加してください。デフォルトのフック設定に {{ic|resume}} フックを追加すると以下のようになります: |
||
+ | # dd if=/dev/zero of=/dev/vg0/swap bs=1M status=progress |
||
− | :{{bc|1=HOOKS="base udev autodetect modconf block '''resume''' filesystems keyboard fsck"}} |
||
+ | ボリュームが完全に割り当てられていることを確認するには、次を使用できます: |
||
− | :変更を適用するために [[mkinitcpio#イメージ作成とアクティベーション|initramfs の再生成]]を忘れずに行ってください。 |
||
+ | {{hc|# lvs| |
||
− | :{{Note|[[LVM]] を使っている場合は {{ic|resume}} フックを {{ic|lvm2}} の後に追加してください。}} |
||
+ | LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert |
||
+ | swap vg0 Vwi-aot--- 10.00g pool 100 |
||
+ | }} |
||
+ | 完全に割り当てられたボリュームは、100%のデータ使用量であると表示されます。 |
||
− | * initramfs で {{ic|systemd}} フックを使っている場合は、復帰機構が既に提供されているので、フックを追加する必要はありません。 |
||
+ | |||
+ | {{Warning|休止状態に使用される thinly-provisioned されたスワップボリュームで [[TRIM]] を使用しないでください。つまり、 {{ic|/etc/fstab}} で {{ic|discard}} を使用しないでください。 ''swapon'' の {{ic|-d}}/{{ic|--discard}} オプション。 そうしないと、使用済みスペースの割り当てが解除されます。}} |
||
+ | |||
+ | === Zswap のライトバックを無効化し、スワップ領域をハイバネートのみに使用する === |
||
+ | |||
+ | Linux 6.8 で zswap は [https://git.kernel.org/linus/501a06fe8e4c185bbda371b8cedbdf1b23a633d8 cgroup 毎にライトバックを無効化するオプションを設定できるようになりました]。Systemd ユニットを使ってすべてのユニットタイプに対して {{ic|MemoryZSwapWriteback}} ({{man|5|systemd.resource-control|Memory Accounting and Control}} を参照) を設定することで、zswap のライトバックを効果的に完全に無効化することができます。これにより、zswap をハイバネートサポートのある zram のように使用できるようになります。 |
||
+ | |||
+ | {{AUR|zswap-disable-writeback}} を[[インストール]]すれば、それぞれタイプに対してトップレベルのドロップインファイルを12個 (システムとユーザーに対して {{ic|scope}}、{{ic|service}}、{{ic|slice}}、{{ic|socket}}、{{ic|mount}}、{{ic|swap}}) わざわざ作らなくてすみます。設定を適用するために再起動してください。 |
||
+ | |||
+ | 何かメモリを大量に消費するタスクを行って zswap がディスクに書き込まないことを確認してください: |
||
+ | |||
+ | {{hc|# cat /sys/kernel/debug/zswap/written_back_pages| |
||
+ | 0 |
||
+ | }} |
||
+ | |||
+ | == スリープフック == |
||
+ | |||
+ | === カスタムの systemd ユニット === |
||
+ | |||
+ | [[systemd]] は、スリープ状態に応じて {{ic|suspend.target}}、{{ic|hibernate.target}}、{{ic|hybrid-sleep.target}}、{{ic|suspend-then-hibernate.target}} のどれかを開始します。これらの target は全て、{{ic|sleep.target}} も開始します。これらの target はどれも、サスペンド/ハイバネートの前や後に[[systemd#ユニットファイル|カスタムのユニット]]を実行するために使用することができます。ユーザーのアクション用と root ユーザー/システムのアクション用とで、別々のファイルを作成する必要があります。例えば: |
||
+ | |||
+ | {{hc|/etc/systemd/system/user-suspend@.service|2= |
||
+ | [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 |
||
+ | }} |
||
+ | |||
+ | {{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-sleep.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 と同じサイズの未フォーマットパーティションとして表示されます。 |
||
+ | |||
+ | {{Warning|Intel Rapid Start パーティションは暗号化されていません。「Intel は、あなたがソフトウェアベースのディスク暗号化を使用している場合、Intel Rapid Start Technology を無効化することを推奨します。」[https://www.intel.com/content/www/us/en/support/articles/000024080/technologies.html]}} |
||
+ | |||
+ | ドライブ全体を消去してパーティションを切り直すつもりなら (あるいはすでにそうしてしまっているなら) 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 のサポートを有効にする必要がある場合もあります。 |
||
+ | |||
+ | {{Tip|(サスペンド後に)IRST が開始されるまでの時間は、システムのファームウェア設定で調整できます。}} |
||
+ | |||
+ | IRST ハイバネートにかかる時間 (つまり、"RAMの内容全体を特殊なパーティションに" コピーする時間) は、システムの RAM サイズと SSD 速度によって異なり、20~60秒かかります。システムによっては、プロセスの完了を(点滅を止めるなどして) LED インジケータで示す場合があります。 |
||
+ | |||
+ | 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] を見てください。 |
||
+ | |||
+ | 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] も見てください。 |
||
== トラブルシューティング == |
== トラブルシューティング == |
||
127行目: | 397行目: | ||
'''DSDT table''' を動作するように設定することができます。[[DSDT]] の記事を参照してください。 |
'''DSDT table''' を動作するように設定することができます。[[DSDT]] の記事を参照してください。 |
||
+ | === サスペンド/ハイバネートが動作しない、あるいはたまに動作しなくなる === |
||
− | === VAIO ユーザー === |
||
+ | ハイバネートやサスペンドから復帰した時に画面が真っ暗になって、明確なエラーは表示されず、何もできなくなるという報告が多数存在します。これらの問題は、ノートパソコンとデスクトップの両方で確認されています。公式の解決方法ではありませんが、古いカーネル、特に LTS カーネルに切り替えることで問題が解決することがあります。 |
||
− | {{ic|1=acpi_sleep=nonvs}} カーネルフラグをブートローダに追加してください、これで OK です! |
||
+ | ハードウェアの watchdog タイマーを使用している場合に問題が起こることもあります (デフォルトで無効化されています、{{man|5|systemd-system.conf|OPTIONS}} の {{ic|1=RuntimeWatchdogSec=}} を見てください)。バグのある watchdog タイマーにより、システムがハイバネートイメージの作成を終える前に、コンピュータがリセットされることがあります。 |
||
− | === サスペンド/ハイバネートが動作しない、あるいはたまに動作しなくなる === |
||
+ | 時々、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] も確認してください。 |
||
− | サスペンドやハイバネートをした場合、あるいは復帰した場合に画面が表示されなくなるという報告が多数存在します。ノートパソコンとデスクトップの両方で問題は確認されています。正式な解決方法ではありませんが、古いカーネル、特に LTS カーネルに切り替えることで問題は解決することがあります。 |
||
+ | [[ATI]] ビデオドライバから新しい [[AMDGPU]] ドライバに移行すると、ハイバネートと復帰のプロセスを成功させることができる可能性があります。 |
||
− | initramfs からのデバイスの初期化によって画面が表示されなくなっていることもあります。[[Mkinitcpio#MODULES]] に追加したモジュールを削除して initramfs を再生成することで問題が解決するかもしれません。特にグラフィックドライバの[[Kernel_Mode_Setting#Early_KMS_start|モジュール]]は問題を起こしがちです。復帰するまえにデバイスが初期化されると矛盾状態になってシステムがハイバネートから復帰できなくなります。サスペンドからの復帰の場合は関係ありません。サスペンドやハイバネートの問題をデバッグする際のベストプラクティスが [https://01.org/blogs/rzhang/2015/best-practice-debug-linux-suspend/hibernate-issues こちらの記事] に記載されています。 |
||
+ | |||
+ | [[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 === |
||
143行目: | 423行目: | ||
=== サスペンドからすぐに復帰する === |
=== サスペンドからすぐに復帰する === |
||
+ | [[電源管理/復帰トリガー#サスペンドからすぐに復帰する]] を見てください。 |
||
− | 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]。 |
||
+ | === ハイバネートした時にシステムの電源が落ちない === |
||
− | サスペンド中に USB デバイスを接続したときなどに ACPI の復帰トリガーが有効になって復帰してしまいます。ブラックリストに追加されるまで一時的な応急処置としては復帰トリガーを無効化する方法があります。以下の設定で USB による復帰を無効化することができます [https://bbs.archlinux.org/viewtopic.php?pid=1575617]。 |
||
+ | システムをハイバネートすると、(現在の状態がディスクに保存されたあとに) システムの電源が切られるはずです。一部のファームウェアでは、S4 スリープ状態が正しく機能しないことがあります。例えば、電源が切られず、システムが再起動してしまうことがあります。そのような場合、{{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 |
+ | 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" タグを追加してください: |
||
+ | |||
+ | {{hc|/etc/udev/rules.d/70-power-switch-my.rules|2= |
||
+ | 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#新しいルールをロードする|上記の udev ルールを再読み込み]]して {{ic|systemd-logind.service}} を[[再起動]]したら、''logind'' の journal に {{ic|Watching system buttons on /dev/input/event6}} という出力が現れるはずです。 |
||
+ | |||
+ | === システムが60秒間フリーズした後に復帰する、または復帰後にハングアップする === |
||
+ | |||
+ | Systemd v256 以降、systemd がスリープ前に {{ic|user.slice}} をフリーズさせるようになりました。これは、(特に KVM が使用されている場合) カーネルのバグにより失敗する可能性があります。[https://github.com/systemd/systemd/issues/33083][https://github.com/systemd/systemd/issues/33626] |
||
+ | |||
+ | スリープ前に {{ic|Failed to freeze unit 'user.slice'}} というメッセージがログに残されます。このような問題が起こると、ログイン (他のセッションを開始する) は {{ic|pam_systemd(''process'':session): Failed to create session: Job 9876 for unit 'session-6.scope' failed with 'frozen'}} というエラーで失敗します。 |
||
+ | |||
+ | 古い systemd の挙動に一時的に戻すには、{{ic|systemd-suspend.service}}、{{ic|systemd-hibernate.service}}、{{ic|systemd-hybrid-sleep.service}}、{{ic|systemd-suspend-then-hibernate.service}} を以下のようなドロップインファイルで[[編集]]してください: |
||
+ | |||
+ | {{bc|1= |
||
+ | [Service] |
||
+ | Environment=SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false |
||
+ | }} |
||
+ | {{TranslationStatus|Power management/Suspend and hibernate|2024-08-25|814767}} |
||
− | 上記のコマンドでサスペンドが再度機能するようになります。ただし、設定は一時的なものなので再起動するたびに設定し直す必要があります。自動化したい場合は [[systemd#カスタム .service ファイルを書く]]を見てください。詳しくは [https://bbs.archlinux.org/viewtopic.php?pid=1575617#p1575617 BBS スレッド] を参照。 |
2024年8月25日 (日) 17:24時点における最新版
関連記事
サスペンドの複数の方法を利用できます。とりわけ:
- Suspend to idle
- Intel は S0ix と呼んでおり、Microsoft は Modern Standby (以前は "Connected Standby") と呼んでいます。Linux カーネルでは S2Idle と呼ばれています。サポートされているシステムにおいて S3 スリープ状態の代わりに使用されるように設計されており、同等の節電機能を提供しますが、復帰に掛かる時間が大幅に短縮されます。
- Suspend to RAM (サスペンド)
- ACPI で S3 スリープ状態として定義されています。RAM を除くマシンのほとんど全てのパーツの電源を切ります。RAM への電源はマシンの状態を保存するために必要です。電力を多く節約できるので、ラップトップでは、バッテリーでコンピュータが稼働していてフタが閉じられた時 (もしくはユーザーが長い間操作しなかった時) は自動的にこのモードに移行するのが得策でしょう。
- Suspend to disk (ハイバネートとも呼ばれます)
- ACPI で S4 スリープ状態として定義されています。マシンの状態をスワップ領域に保存してマシンの電源を完全にオフにします。マシンに電源を入れた時、状態が復元されます。それまでは、電力消費量はゼロです。
- Hybrid suspend (ハイブリットスリープとも呼ばれます)
- サスペンドとハイバネートのハイブリッドです。Suspend to both と呼ばれることもあります。マシンの状態をスワップ領域に保存しますが、マシンの電源を切りません。代わりに、デフォルトのサスペンドを呼び出します。これによって、バッテリーを使いきっても、システムは即座に復帰できます。バッテリーが枯渇した時は、システムはディスクから復帰し、RAM からの復帰に比べて時間がかかりますが、システムの状態が失われることはありません。
カーネルは、基本的な機能を提供しており、問題のあるハードウェアドライバ/カーネルモジュール (例: ビデオカードの再初期化) に対処する機能を提供する高レベルなインターフェイスもいくつかあります。
目次
- 1 カーネルのインターフェイス (swsusp)
- 2 高レベルインターフェイス (systemd)
- 3 サスペンドの方法を変更する
- 4 ハイバネーション
- 5 スリープフック
- 6 ヒントとテクニック
- 7 トラブルシューティング
- 7.1 ACPI_OS_NAME
- 7.2 サスペンド/ハイバネートが動作しない、あるいはたまに動作しなくなる
- 7.3 Wake-on-LAN
- 7.4 サスペンドからすぐに復帰する
- 7.5 ハイバネートした時にシステムの電源が落ちない
- 7.6 ハイバネート後に起動するとオペレーティングシステムが見つからない (または、間違った OS が起動する)
- 7.7 /home にスワップファイルを置く
- 7.8 A520I および B550I マザーボードで PC がスリープから復帰しない
- 7.9 ノートパソコンをサスペンドする Fn キーが動作しない
- 7.10 システムが60秒間フリーズした後に復帰する、または復帰後にハングアップする
カーネルのインターフェイス (swsusp)
カーネル内のソフトウェアサスペンドコード (swsusp) にサスペンド状態に入るよう直接伝えることは可能です。実際の方法と状態はハードウェアサポートのレベルによります。最近のカーネルでは、サスペンドにするために /sys/power/state
に適切な文字列を書くことが主な方法になっています。
詳しくは カーネルドキュメント を参照してください。
高レベルインターフェイス (systemd)
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 スリープと同じ節電機能を提供しないシステム、あるいは、電力を節約することが復帰を高速化することよりも優先される場合においては、デフォルトのサスペンド方法を変更することが可能です。
以下のコマンドは、ハードウェアによってサポートされていると広告されている全てのサスペンド方法を出力します (現在のサスペンド方法は角括弧に囲まれます[1]):
$ cat /sys/power/mem_sleep
[s2idle] shallow deep
mem_sleep 文字列 | スリープ状態 |
---|---|
s2idle | suspend-to-idle |
shallow | standby |
deep | suspend-to-RAM |
ハードウェアが deep
スリープ状態を広告していない場合、UEFI にそのような設定がないか確認してください。通常、Power や Sleep state などのような項目にあります。S0ix のオプションは Windows 10 や Windows and Linux や S3/Modern standby support という名前です。S3 スリープのオプションは Legacy、Linux、Linux S3、S3 enabled という名前です。設定できない場合、s2idle
を使い続けることもできます、ハイバネート を使うことを検討するか、DSDT テーブルにパッチを当ててみてください (あるいは、パッチ適用済みのバージョンを見つけてください)。
スリープの方法を変更したあと、スリープサイクルを何回かテストして、ハードウェアが S3 スリープで問題を起こさないかテストしてください:
# echo deep > /sys/power/mem_sleep
問題が無ければ、mem_sleep_default=deep
カーネルパラメータ か、もしくは systemd-sleep.conf(5) の MemorySleepMode
ディレクティブで変更を永続化することができます:
/etc/systemd/sleep.conf.d/mem-deep.conf
[Sleep] MemorySleepMode=deep
いくつかの逆の状況では、問題のあるファームウェアが s2idle
しかサポートしていないにも関わらず、deep
をサポートしていると広告することがあります。この場合、SuspendState
設定を使うことにより、s2idle
を使うことができます:
/etc/systemd/sleep.conf.d/freeze.conf
[Sleep] SuspendState=freeze
ハイバネーション
ハイバネートを行うには、次のことを行う必要があります: スワップパーティションかスワップファイルの作成する。初期ユーザー空間で復帰プロセスを初期化できるようにするために initramfs を設定する。Initramfs から利用できる方法でスワップ領域の場所を指定する (例えば、HibernateLocation
EFI 変数を systemd で定義したり、resume=
カーネルパラメータを設定したり)。これらの3つの手順は以下で詳細に説明されています。
スワップパーティション(ファイル)のサイズについて
スワップパーティションが 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.conf
にresume
フックを追加する必要があります。ラベルあるいは UUID どちらを使用している場合でもスワップパーティションは udev デバイスノードによって参照されるので、resume
フックはudev
フックの後に追加する必要があります。デフォルトのフック設定にresume
フックを追加すると以下のようになります:
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block filesystems resume fsck)
- 変更を適用するために initramfs の再生成を忘れずに行ってください。
- 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/resume
に major: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
ハイバネート用のスワップファイルを zram で保持する
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%のデータ使用量であると表示されます。
Zswap のライトバックを無効化し、スワップ領域をハイバネートのみに使用する
Linux 6.8 で zswap は cgroup 毎にライトバックを無効化するオプションを設定できるようになりました。Systemd ユニットを使ってすべてのユニットタイプに対して MemoryZSwapWriteback
(systemd.resource-control(5) § Memory Accounting and Control を参照) を設定することで、zswap のライトバックを効果的に完全に無効化することができます。これにより、zswap をハイバネートサポートのある zram のように使用できるようになります。
zswap-disable-writebackAUR をインストールすれば、それぞれタイプに対してトップレベルのドロップインファイルを12個 (システムとユーザーに対して scope
、service
、slice
、socket
、mount
、swap
) わざわざ作らなくてすみます。設定を適用するために再起動してください。
何かメモリを大量に消費するタスクを行って zswap がディスクに書き込まないことを確認してください:
# cat /sys/kernel/debug/zswap/written_back_pages
0
スリープフック
カスタムの systemd ユニット
systemd は、スリープ状態に応じて suspend.target
、hibernate.target
、hybrid-sleep.target
、suspend-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.service
や user-resume@user.service
を有効化してください。
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 は、/usr/lib/systemd/system-sleep/
内の全ての実行可能ファイルを実行します。このとき、2つの引数が渡されます:
pre
またはpost
: マシンがスリープしようとしているのか、復帰しようとしているのか。suspend
、hibernate
、hybrid-sleep
のどれか: どのスリープ状態が実行される/されたのか。
カスタムスクリプトの出力は、systemd-suspend.service や systemd-hibernate.service、systemd-hybrid-sleep.service によって記録されます。systemd の journalctl でこのログを見ることができます:
# 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-sleep.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 と同じサイズの未フォーマットパーティションとして表示されます。
ドライブ全体を消去してパーティションを切り直すつもりなら (あるいはすでにそうしてしまっているなら) IRST パーティションも再作成しなければなりません。これを行うには、システムの RAM と同じサイズの空のパーティションを作成し、そのパーティションの種類が GPT パーティションの場合は GUID D3BFE2DE-3DAF-11DF-BA40-E3A556D89593
に、 MBR パーティションの場合は ID 0x84
に設定します。また、システムのファームウェア設定で IRST のサポートを有効にする必要がある場合もあります。
IRST ハイバネートにかかる時間 (つまり、"RAMの内容全体を特殊なパーティションに" コピーする時間) は、システムの RAM サイズと SSD 速度によって異なり、20~60秒かかります。システムによっては、プロセスの完了を(点滅を止めるなどして) LED インジケータで示す場合があります。
Linux カーネルで IRST ハイバネートイベントを設定するには、CONFIG_INTEL_RST
オプションでカーネルに組み込むか、カーネルモジュールとして利用可能である必要があります。modprobe intel_rst
を実行してモジュールをロードすれば、/sys/bus/acpi/drivers/intel_rapid_start/*/
にファイル wakeup_events
と wakeup_time
が生成されるはずです。これらを用いて、さらなる設定を行うことができます。このモジュールは簡潔にドキュメント化されています。詳細は drivers/platform/x86/intel/rst.c を見てください。
Intel Rapid Start Technology に関する情報は、general Q&A と user guides も見てください。
トラブルシューティング
ACPI_OS_NAME
DSDT table を動作するように設定することができます。DSDT の記事を参照してください。
サスペンド/ハイバネートが動作しない、あるいはたまに動作しなくなる
ハイバネートやサスペンドから復帰した時に画面が真っ暗になって、明確なエラーは表示されず、何もできなくなるという報告が多数存在します。これらの問題は、ノートパソコンとデスクトップの両方で確認されています。公式の解決方法ではありませんが、古いカーネル、特に LTS カーネルに切り替えることで問題が解決することがあります。
ハードウェアの watchdog タイマーを使用している場合に問題が起こることもあります (デフォルトで無効化されています、systemd-system.conf(5) § OPTIONS の RuntimeWatchdogSec=
を見てください)。バグのある 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 が有効になっている場合、コンピュータがハイバネート状態になっていてもネットワークインターフェイスカードによって電力が消費されます。
サスペンドからすぐに復帰する
電源管理/復帰トリガー#サスペンドからすぐに復帰する を見てください。
ハイバネートした時にシステムの電源が落ちない
システムをハイバネートすると、(現在の状態がディスクに保存されたあとに) システムの電源が切られるはずです。一部のファームウェアでは、S4 スリープ状態が正しく機能しないことがあります。例えば、電源が切られず、システムが再起動してしまうことがあります。そのような場合、sleep.conf.d(5) で HibernateMode
の値を shutdown
に設定すると良いかもしれません:
/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
という出力が現れるはずです。
システムが60秒間フリーズした後に復帰する、または復帰後にハングアップする
Systemd v256 以降、systemd がスリープ前に user.slice
をフリーズさせるようになりました。これは、(特に KVM が使用されている場合) カーネルのバグにより失敗する可能性があります。[10][11]
スリープ前に Failed to freeze unit 'user.slice'
というメッセージがログに残されます。このような問題が起こると、ログイン (他のセッションを開始する) は pam_systemd(process:session): Failed to create session: Job 9876 for unit 'session-6.scope' failed with 'frozen'
というエラーで失敗します。
古い systemd の挙動に一時的に戻すには、systemd-suspend.service
、systemd-hibernate.service
、systemd-hybrid-sleep.service
、systemd-suspend-then-hibernate.service
を以下のようなドロップインファイルで編集してください:
[Service] Environment=SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false