Im Linux-Kernel ist der Suspend/Resume-Prozess ein sehr wichtiger Prozess. Es kann den Ruhezustand und das Aufwachen des Systems realisieren und die Energieeffizienz und Reaktionsgeschwindigkeit des Systems verbessern. In diesem Artikel befassen wir uns mit den Implementierungsprinzipien und verwandten Technologien des Suspend/Resume-Prozesses des Linux-Kernels.
Ruhezustand/Aufwachen ist ein sehr wichtiger Teil in eingebettetem Linux. Eingebettete Geräte sollten so weit wie möglich in den Ruhezustand wechseln, um die Batterielebensdauer zu verlängern. In diesem Artikel wird detailliert beschrieben, wie Schlaf/Aufwecken unter Linux funktioniert
Referenzartikel: Autor: zhangjiejing Datum: 07.04.2010, http://www.thinksrc.com
Eine kurze Einführung in den Winterschlaf
Unter Linux ist der Ruhezustand hauptsächlich in drei Hauptschritte unterteilt:
1. Benutzermodusprozesse und Kernelmodusaufgaben einfrieren
2. Rufen Sie die Suspend-Callback-Funktion des registrierten Geräts auf
3. Die Reihenfolge richtet sich nach der Anmeldereihenfolge
Kerngeräte in den Ruhezustand versetzen und die CPU in den Ruhezustand versetzen, bedeutet, dass der Kernel den Status aller Prozesse in der Prozessliste auf „Gestoppt“ setzt und den Kontext aller Prozesse speichert, wenn sie nicht eingefroren sind Wenn es eingefroren ist, wird es einfach weiter ausgeführt. Wie können Benutzer das System so steuern, dass es in den Ruhezustand wechselt, indem sie beispielsweise die Systemdatei /sys /power/state lesen und schreiben
# echo mem > /sys/power/state
Befehlen Sie dem System, in den Ruhezustand zu gehen. Kann auch verwendet werden
# cat /sys/power/state
Um herauszufinden, welche Schlafmodi vom Kernel unterstützt werden.
Linux-Suspend-Prozess
Zugehörige Dokumente:
Sie können den Quellcode erhalten, indem Sie die Linux-Kernel-Website besuchen. Hier ist der Pfad zur Datei:
kernel/kernel/power/main.c kernel/kernel/power/suspend.c kernel/driver/base/power/main.c
Lassen Sie uns einen genaueren Blick darauf werfen, wie Linux in den Ruhezustand wechselt/aufwacht.
Das Lesen und Schreiben von /sys/power/state durch Benutzer ruft state_store() in main.c auf. Benutzer können in const char * const pm_state[] definierte Zeichenfolgen schreiben, z. B. „mem“, „standby“. Die Steuerung erfolgt normalerweise über die Suspend- und Resume-Tasten
Dann ruft state_store() enter_state() auf, das zunächst einige Statusparameter überprüft und dann das Dateisystem synchronisiert. Hier ist der Code:
1. /** 2. \* enter_state - Do common work of entering low-power state. 3. \* @state: pm_state structure for state we're entering. 4. \* 5. \* Make sure we're the only ones trying to enter a sleep state. Fail 6. \* if someone has beat us to it, since we don't want anything weird to 7. \* happen when we wake up. 8. \* Then, do the setup for suspend, enter the state, and cleaup (after 9. \* we've woken up). 10. */ 11. int enter_state(suspend_state_t state) 12. { 13. int error; 14. 15. if (!valid_state(state)) 16. return -ENODEV; 17. 18. if (!mutex_trylock(&pm_mutex)) 19. return -EBUSY; 20. 21. printk(KERN_INFO "PM: Syncing filesystems ... "); 22. sys_sync(); 23. printk("done.\n"); 24. 25. pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]); 26. error = suspend_prepare(); 27. if (error) 28. goto Unlock; 29. 30. if (suspend_test(TEST_FREEZER)) 31. goto Finish; 32. 33. pr_debug("PM: Entering %s sleep\n", pm_states[state]); 34. pm_restrict_gfp_mask(); 35. error = suspend_devices_and_enter(state); 36. pm_restore_gfp_mask(); 37. 38. Finish: 39. pr_debug("PM: Finishing wakeup.\n"); 40. suspend_finish(); 41. Unlock: 42. mutex_unlock(&pm_mutex); 43. return error; 44. }
Vorbereiten, Prozess einfrieren
Nach der Eingabe von suspend_prepare() wird ein virtuelles Terminal zum Anhalten zugewiesen, um Informationen auszugeben. Anschließend wird eine Benachrichtigung gesendet, dass das System in den Suspend-Zustand wechseln möchte, der Benutzermodus-Hilfsprozess geschlossen und anschließend suspend_freeze_processes() nacheinander aufgerufen, um alles einzufrieren Prozesse, der aktuelle Status aller Prozesse wird hier gespeichert. Möglicherweise gibt es einige Prozesse, die sich weigern, in den eingefrorenen Zustand zu wechseln die waren einfach eingefroren
1. /** 2. \* suspend_prepare - Do prep work before entering low-power state. 3. \* 4. \* This is common code that is called for each state that we're entering. 5. \* Run suspend notifiers, allocate a console and stop all processes. 6. */ 7. static int suspend_prepare(void) 8. { 9. int error; 10. 11. if (!suspend_ops || !suspend_ops-**>**enter) 12. return -EPERM; 13. 14. pm_prepare_console(); 15. 16. error = pm_notifier_call_chain(PM_SUSPEND_PREPARE); 17. if (error) 18. goto Finish; 19. 20. error = usermodehelper_disable(); 21. if (error) 22. goto Finish; 23. 24. error = suspend_freeze_processes(); 25. if (!error) 26. return 0; 27. 28. suspend_thaw_processes(); 29. usermodehelper_enable(); 30. Finish: 31. pm_notifier_call_chain(PM_POST_SUSPEND); 32. pm_restore_console(); 33. return error; 34. }
Peripheriegeräte in den Ruhezustand versetzen
Jetzt wurden alle Prozesse (einschließlich Arbeitswarteschlange/kthread) gestoppt, wenn sie angehalten werden. Wenn Sie also die Semaphore im Peripheriegerät zu diesem Zeitpunkt entsperren, kann es zu einer Sperre kommen. Seien Sie daher beim Sperren sehr vorsichtig /Unlocking in der suspend()-Funktion des Peripheriegeräts wird empfohlen, beim Entwerfen nicht auf die Sperre in suspend() zu warten. Da einige Protokolle während des Suspendierens nicht ausgegeben werden können, ist das Debuggen sehr schwierig
Dann wird der Kernel versuchen, hier etwas Speicher freizugeben.Abschließend wird suspend_devices_and_enter() aufgerufen, um alle Peripheriegeräte in den Ruhezustand zu versetzen. Wenn die Plattform suspend_pos registriert (normalerweise in der Definition auf Platinenebene definiert und registriert), wird hier suspend_ops->begin() aufgerufen dann wird device_suspend()->dpm_suspend() in drivers/base/power/main.c aufgerufen, und sie rufen nacheinander den suspend()-Rückruf des Treibers auf, um alle Geräte in den Ruhezustand zu versetzen.
Wenn alle Geräte in den Ruhezustand wechseln, wird suspend_ops->prepare() aufgerufen. Diese Funktion führt normalerweise einige Vorbereitungsarbeiten durch, um das Board in den Ruhezustand zu versetzen. Als nächstes wird die nicht startende CPU in Multi-Core-CPUs geschaltet Ausschalten, wie Sie den Kommentaren entnehmen können, dient dazu, die durch diese anderen CPUs verursachte Rennbedingung zu vermeiden. Von nun an wird nur noch eine CPU ausgeführt.
suspend_ops ist ein Energieverwaltungsvorgang auf Platinenebene, der normalerweise in der Datei arch/xxx/mach-xxx/pm.c. registriert ist.
Als nächstes wird suspend_enter() aufgerufen, um den Arch-IRQ zu schließen und die Funktion suspend_late() aufzurufen. Dies ist normalerweise die letzte Funktion, die aufgerufen wird Wird in dieser Funktion durchgeführt. Wenn die Prüfung in Ordnung ist, werden alle Systemgeräte und Busse in den Ruhezustand versetzt und die CPU wird zu diesem Zeitpunkt bereits in den Ruhezustand versetzt die Ausführung des Codes stoppt
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 过程的实现原理和相关技术。
Das obige ist der detaillierte Inhalt vonAusführliche Diskussion der Implementierungsprinzipien und verwandten Technologien des Suspend/Resume-Prozesses des Linux-Kernels. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!