Linuxカーネルのシステムシャットダウンは内部でどのように機能しますか?


28

システムのシャットダウン時に、ユーザー空間とinit-system(従来のinit sysV / upstart / systemdである)がどのように機能するかについての大まかな考えがあります。(本質的には、「Stop!」、「本当に今すぐ停止してください」、「停止するためにあなたを殺す必要があるプロセス」の順番の連続があり、待っています...事が起こっています)。

私はとにかくカーネルでシステムのシャットダウンがどのように機能するのか非常に知りません(確かに多くのこともあります)?

私は、カーネルのドキュメントに見てみましたhttps://www.kernel.org/doc/htmldocs/も使用NSAのPAL検索ツールを私にそれがどのように動作するかを見つけ出すのヘッドスタートを与えます。

また、SE U + Lを検索しても何も見つかりませんでした(見落としていませんか?)

とにかく、質問は少し難しいかもしれませんが、シャットダウン時にLinuxカーネルで何が起こるかについてより多くの人が興味を持っていると思うので、このQ&Aネットワークでは答えに値します。

さらに詳細な説明にリンクする変更もある可能性があります。

答えには、どのシステムコールとどのカーネル信号が使用されているかが含まれる場合がありますか?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c はリブートに関連するx86使用ファイルのようです(すでにシャットダウンに近いですか?)

ここにあるスニペットhttp://lxr.free-electrons.com/source/kernel/reboot.c#L176 を使用して説明することができます

176 void kernel_power_off(void)
177 {
178 kernel_shutdown_prepare(SYSTEM_POWER_OFF);
179 if(pm_power_off_prepare)
180 pm_power_off_prepare();
181 migrate_to_reboot_cpu();
182 syscore_shutdown();
183 pr_emerg( "Power down \ n");
184 kmsg_dump(KMSG_DUMP_POWEROFF);
185 machine_power_off();
186}
187 EXPORT_SYMBOL_GPL(kernel_power_off);

8
ユニコーンがあなたと一緒に
いらっしゃい

1
@Kiwyの提案に感謝します。より良い答えが出てくるまでしばらく時間が経った後、私は受け入れます。しかし、少なくともいくつかの答えは今そこにあります。
humanityANDpeace 14

感謝しません、ユニコーンに感謝します!
Kiwy 14

/だったがあることに注意してください窓の外にジャンプするためのオプションshutdown(8)、すなわち、非推奨 -n私は1つだと思う読み取るために使用される古いUNIXのマニュアルの「システムをシャットダウン自分自身! -コアユニットがON FIREでの」効果的に厄介なシステムキルスイッチましたビットが床に散らばる(または少なくとも破損した状態のファイルシステム)ままになる可能性があります-これは、誰かが冷却ファンに手を引っ掛けたばかりのメインフレームタイプのシステムに使用されると想像されます。🕱
SlySven

回答:


26

Linuxカーネルの動作を理解するための主なリソースは次のとおりです。

  1. ドキュメント
  2. Linux Weekly Newsの記事
  3. 起源。これは複雑な獣で、Linuxの相互参照であるLXRを介して理解するのが少し簡単です。lxr.linux.noで実行されるLXRバリアントは他のものよりも優れていますが、多くの場合ダウンしています。

この場合、ドキュメントまたはLWNで中心的に関連するものは見つからないので、LXRです。

ユーザーランドコードが最後に行うことは、rebootシステムコールを呼び出すことです。4つの引数をとるのでSYSCALL_DEFINE4(reboot、LXRで検索すると、につながりkernel/reboot.cます。呼び出し元の特権と引数を確認した後、syscallエントリポイントは、いくつかの関数の1つを呼び出します。kernel_restart再起動、kernel_haltタイトループでの停止kernel_poweroff、システムの電源オフ、カーネルを新しいものkernel_kexec置き換えます(コンパイルされている場合)、またはhibernate電源を切る前にメモリをディスクに保存します。

kernel_restartkernel_haltkernel_power_offかなり類似しています。

  1. 通過するreboot_notifier_listカーネルコンポーネントができることをフックのリストである、登録パワーダウンでコードを実行します。この段階でコードを実行する必要があるドライバーはわずかで、ほとんどがウォッチドッグです。
  2. system_state変数を設定します。
  3. usermode-helperを無効にして、ユーザーコードが開始されないようにします。(この段階でも既存のプロセスが存在する可能性があります。)
  4. device_shutdownシステム上のすべてのデバイスを解放または電源を切るために呼び出します。多くのドライバーがこの段階に入ります。
    この時点でまだマウントされているファイルシステムは、事実上強制的にアンマウントされることに注意してください。システムコールの呼び出し元は、クリーンアンマウントの責任を負います。
  5. 電源オフの場合のみ、ACPIが構成されている場合、コードを実行してACPI 状態S5(ソフト電源オフ)に移行する準備する可能性があります。
  6. マルチCPUマシンでは、システムコールを呼び出した任意のCPUでコードを実行できます。migrate_to_reboot_cpu特定の1つのCPUに切り替え、スケジューラが他のCPUにコードをディスパッチしないように注意します。この時点以降、単一のCPUのみが実行されます。
  7. syscore_shutdown登録されたsyscore操作のshutdownメソッドを呼び出します。これは主に割り込みを無効にすることだと思います。いくつかのフックにはメソッドがあります。shutdown
  8. 情報メッセージ—白鳥の歌を記録します。
  9. 最後にmachine_restartmachine_haltまたはを呼び出して、マシンに依存した方法で休憩しmachine_power_offます。

冬眠コードは、以下のステップを経ます:

  1. 電源管理フックを反復処理します。
  2. ファイルシステムを同期します。
  3. すべてのユーザーコードをフリーズします
  4. デバイスのホットプラグを防ぎます
  5. システム状態をスワップスペースにダンプします。
  6. すべてが成功したら、ハードウェアを休止状態にします。これは、呼び出し伴うことができるkernel_restartkernel_haltまたはkernel_power_off、またはいくつかのプラットフォーム固有の冬眠方法。

システムをシャットダウンする別の方法はmachine_emergency_restartです。これは、魔法のSysRqキーBによって呼び出されますOキーは動作が異なります:それが呼び出されますkernel_power_off

システムは、パニック、つまり回復不能なエラーでシャットダウンすることもあります。パニックは、メッセージを記録し、システムを再起動します(ハードウェアウォッチドッグまたは緊急時再起動のいずれかを使用)。


+1ありがとう!@Gillesあなたがlaststepとして/ sanatizeマシンのRAMを拭くでしょういくつかのコードを実装したい場合、あなたがのためにsyscore操作登録しますsyscore_shutdown(つまり、私の他の質問解決することunix.stackexchange.com/q/122540/24394を) 。ステップ(1)とステップ(7)はどちらもシャットダウン時に実行されるものを登録することを許可し、何が何であるかをはっきりさせません+(1)と(7)のコールバックの実行順序は影響を受けないという印象がありました!あなたが言及したドキュメントを紹介しますが、ご存知なら!ありがとう!
humanityANDpeace 14

私はこの質問と答えにこれ以上の賛成票がないことに驚いています。

2

これは部分的な答えにすぎず、他の答えを招待することは間違いありません。

この回答の内容は3.13 Linuxカーネルのkernel/reboot.cファイルから取得されます(名前はshutdown.cではなくreboot.cであるため、これは最初の推測ではない可能性があります)

とにかく、システムをシャットダウンするプロセスをスケッチする基本的に3つの関数があります

  • void kernel_halt(void) //停止状態のシステムで終了します
  • void kernel_power_off(void) //これは、システムの電源がオフになって終了します
  • void kernel_restart(char *cmd) //システムを終了してまだ再起動します

これらの機能は非常に短いため、ここに完全に貼り付けることができます。それらのコードは、カーネルでシャットダウンするためにどのような手順が取られているかを最もよく示しています。(コメントは私によるもので、100%理想的で正確ではないかもしれません。確信があるかどうかを確認してください。これは簡単な試みです。

void kernel_halt(void)

void kernel_halt(void)
{
    //最初のステップは:
    // a)再起動/シャットダウン時に実行するように登録された関数/コールバックを呼び出す
    // b)system_sateをSYSTEM_HALTに設定します
    // c)userspacetoolの対話を停止します
    // d)device_shutdown()関数を呼び出します
    kernel_shutdown_prepare(SYSTEM_HALT);

    // 2番目のステップ:これは主にマルチCPUシステムの必要性だと思います
    migrate_to_reboot_cpu();

    // 3番目のステップ:
    // syscore_shutdown-すべての登録済みシステムコアシャットダウンコールバックを実行します 
    syscore_shutdown();

    // 4番目のメッセージ
    pr_emerg( "System halted \ n");
    kmsg_dump(KMSG_DUMP_HALT);

    // 5番目の呼び出しアーキテクチャ固有のcpu-halt-code
    machine_halt();
}

全体はsys_rebootシステムコールで開始されます。システムコールは、リブートするだけでなくシャットダウンも行うため、シャットダウンプロセスに直接接続することはできません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.