Linux カーネルでは、サスペンド/レジューム プロセスは非常に重要なプロセスです。システムのスリープとウェイクアップを実現し、システムのエネルギー効率と応答速度を向上させることができます。この記事では、Linux カーネルの一時停止/再開プロセスの実装原理と関連テクノロジについて詳しく説明します。
ハイバネーション/ウェイクアップは、組み込み Linux において非常に重要な部分です。組み込みデバイスは、バッテリ寿命を延ばすために、可能な限りスリープ状態に入ります。この記事では、Linux でスリープ/ウェイクアップがどのように機能するかを詳しく紹介します
参考記事: 著者: zhangjiejing
私の Linux カーネル バージョン: 3.0.31
冬眠についての簡単な紹介
Linux では、休止状態は主に 3 つの主要なステップに分かれています:
1. ユーザーモードプロセスとカーネルモードタスクを凍結する
2. 登録したデバイスのサスペンドコールバック関数を呼び出します
3. 順序は登録順です
コア デバイスを休止状態にし、CPU を休止状態にします。プロセスを凍結すると、カーネルがプロセス リスト内のすべてのプロセスのステータスを停止に設定し、すべてのプロセスのコンテキストを保存します。これらのプロセスが凍結解除されると、プロセスは、 Linux を休止状態にするにはどうすればよいですか? ユーザーは、sys ファイル /sys /power/state を読み書きすることによって、システムが休止状態に入るように制御できます。例:
# エコーメモリ > /sys/power/state
システムに休止状態に入るように命令します。
を使用することもできます。# cat /sys/power/state
カーネルがサポートしているスリープ モードを確認するには。
Linux サスペンドプロセス
関連資料:
Linux カーネル Web サイトにアクセスしてソース コードを入手できます。ファイルへのパスは次のとおりです:
リーリーLinux がどのようにスリープ/ウェイクアップするかを詳しく見てみましょう。これらがどのように起こるかを見てみましょう。
ユーザーによる /sys/power/state の読み取りと書き込みは、main.c の state_store() を呼び出します。ユーザーは、「mem」、「standby」など、const char * const pm_state[] で定義された文字列を書き込むことができます。もちろん、通常は一時停止ボタンと再開ボタンによって制御されます
次に、state_store() は enter_state() を呼び出します。これにより、最初にいくつかの状態パラメータがチェックされ、次にファイル システムが同期されます。コードは次のとおりです:
リーリー準備、凍結プロセス
suspend_prepare() を入力すると、情報を出力するために一時停止する仮想端末を割り当て、システムが一時停止に入りたいことを通知する通知をブロードキャストし、ユーザー モード ヘルパー プロセスを閉じてから、suspend_freeze_processes() を順番に呼び出します。すべてのプロセスを凍結すると、すべてのプロセスの現在の状態がここに保存されます。凍結状態になることを拒否するプロセスが存在する可能性があります。そのようなプロセスが存在する場合、凍結は失敗します。この機能は、凍結されたプロセスを放棄し、すべてのプロセスの凍結を解除します。凍結されたばかりです。process.
リーリー周辺機器をスリープ状態にする
現在、すべてのプロセス (ワークキュー/kthread を含む) が停止しています。カーネル モードの文字は停止時にいくつかのセマフォを保持している可能性があるため、この時点でペリフェラルのセマフォのロックを解除すると、デッドロックが発生する可能性があります。ペリフェラルのsuspend()関数でのロック/ロック解除には注意してください。設計時はsuspend()でのロックを待たないことを推奨します。また、サスペンド時は一部のログが出力できないため、一度問題が発生すると非常に危険です。デバッグが難しい。
その後、カーネルはここでメモリを解放しようとします。
最後に、suspend_devices_and_enter() が呼び出され、すべてのペリフェラルをスリープ状態にします。この関数では、プラットフォームが stop_pos を登録する場合 (通常はボードレベルの定義で定義および登録されます)、ここで stop_ops->begin() が呼び出されます。 . . 次に、driver/base/power/main.c の device_suspend()->dpm_suspend() が呼び出され、ドライバーのサスペンド() コールバックを順番に呼び出して、すべてのデバイスをスリープさせます。
すべてのデバイスがスリープ状態になると、suspend_ops->prepare() が呼び出されます。この関数は通常、ボードをスリープ状態にするための準備作業を行います。次に、Linux では、マルチコア CPU 内の非起動 CPUコメントからわかるように、他の CPU が競合状態を引き起こすのを防ぐためです。今後は 1 つの CPU のみが実行されます。suspend_ops はボードレベルの電源管理操作であり、通常はファイル Arch/xxx/mach-xxx/pm.c.
に登録されます。
次に、suspend_enter() が呼び出されます。この関数は、アーチ IRQ を閉じ、device_power_down() を呼び出し、そして、suspend_late() 関数を呼び出します。この関数は、システムが実際にスリープ状態に入ったときに呼び出される最後の関数です。通常、この関数で呼び出されます。最終チェックを行い、チェックが OK であれば、すべてのシステム デバイスとバスをスリープし、suspend_pos->enter() を呼び出して CPU を省電力状態にします。はすでにスリープ状態です。コードの実行はここで停止されています
1. /** 2. \* suspend_devices_and_enter - suspend devices and enter the desired system 3. \* sleep state. 4. \* @state: state to enter 5. */ 6. int suspend_devices_and_enter(suspend_state_t state) 7. { 8. int error; 9. 10. if (!suspend_ops) 11. return -ENOSYS; 12. 13. trace_machine_suspend(state); 14. if (suspend_ops-**>**begin) { 15. error = suspend_ops-**>**begin(state); 16. if (error) 17. goto Close; 18. } 19. suspend_console(); 20. suspend_test_start(); 21. error = dpm_suspend_start(PMSG_SUSPEND); 22. if (error) { 23. printk(KERN_ERR "PM: Some devices failed to suspend\n"); 24. goto Recover_platform; 25. } 26. suspend_test_finish("suspend devices"); 27. if (suspend_test(TEST_DEVICES)) 28. goto Recover_platform; 29. 30. error = suspend_enter(state); 31. 32. Resume_devices: 33. suspend_test_start(); 34. dpm_resume_end(PMSG_RESUME); 35. suspend_test_finish("resume devices"); 36. resume_console(); 37. Close: 38. if (suspend_ops-**>**end) 39. suspend_ops-**>**end(); 40. trace_machine_suspend(PWR_EVENT_EXIT); 41. return error; 42. 43. Recover_platform: 44. if (suspend_ops-**>**recover) 45. suspend_ops-**>**recover(); 46. goto Resume_devices; 47. } RESUME
如果在休眠中系统被中断或者其他事件唤醒, 接下来的代码就会开始执行, 这个 唤醒的顺序是和休眠的循序相反的,所以系统设备和总线会首先唤醒,使能系统中 断, 使能休眠时候停止掉的非启动CPU, 以及调用suspend_ops->finish(), 而且 在suspend_devices_and_enter()函数中也会继续唤醒每个设备,使能虚拟终端, 最后调用 suspend_ops->end().
在返回到enter_state()函数中的, 当 suspend_devices_and_enter() 返回以后, 外设已经唤醒了, 但是进程和任务都还是冻结状态, 这里会调用suspend_finish()来解冻这些进程和任务, 而且发出Notify来表示系统已经从suspend状态退出, 唤醒终端.
到这里, 所有的休眠和唤醒就已经完毕了, 系统继续运行了.
总之,suspend/resume过程是Linux内核中不可或缺的一部分。它可以实现系统的休眠和唤醒,提高系统的能效和响应速度。希望本文能够帮助读者更好地理解Linux Kernel suspend/resume 过程的实现原理和相关技术。
以上がLinux カーネルのサスペンド/レジューム プロセスの実装原理と関連テクノロジについての詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。