Linux電源管理(5)_Hibernate和Sleep功能介紹

原文:Linux電源管理(5)_Hibernate和Sleep功能介紹

1. 前言

Hibernate和Sleep兩個功能是Linux PM的核心功能,它們的目的是類似的:暫停使用——>保存上下文——>關閉系統以節電········>恢復系統——>恢復上下文——>繼續使用。

本文以內核向用戶空間提供的接口為突破口,從整體上對這兩個功能進行介紹,并會在后續的文章中,分析它們的實現邏輯和執行動作。

2. Hibernate和Sleep相關的術語梳理

▆ Hibernate(冬眠)和Sleep(睡眠)

是Linux電源管理在用戶角度的抽象,是用戶可以看到的實實在在的東西。它們的共同點,是保存系統運行的上下文后掛起(suspend)系統,并在系統恢復后接著運行,就像什么事情都沒有發生一樣。它們的不同點,是上下文保存的位置、系統恢復的觸發方式以及具體的實現機制。

▆ Suspend

有兩個層次的含義。一是Hibernate和Sleep功能在底層實現上的統稱,都是指掛起(Suspend)系統,根據上下文的保存位置,可以分為Suspend to Disk(STD,即Hibernate,上下文保存在硬盤/磁盤中)和Suspend to RAM(STR,為Sleep的一種,上下文保存在RAM中);二是Sleep功能在代碼級的實現,表現為“kernel/power/suspend.c”文件。

▆ Standby,是Sleep功能的一個特例,可以翻譯為“打盹”。

正常的Sleep(STR),會在處理完上下文后,由arch-dependent代碼將CPU置為低功耗狀態(通常為Sleep)。而現實中,根據對功耗和睡眠喚醒時間的不同需求,CPU可能會提供多種低功耗狀態,如除Sleep之外,會提供Standby狀態,該狀態下,CPU處于淺睡眠模式,有任何的風吹草動,就會立即醒來。

▆ Wakeup

這是我們第一次正式的提出Wakeup的概念。我們多次提到恢復系統,其實在內核中稱為Wakeup。表面上,wakeup很簡單,無論是冬眠、睡眠還是打盹,總得有一個刺激讓我們回到正常狀態。但復雜的就是,什么樣的刺激才能讓我們醒來?

動物界,溫度回升可能是唯一可以讓動物從冬眠狀態醒來的刺激。而踢一腳、鬧鐘響等刺激,則可以讓我們從睡眠狀態喚醒。對于打盹來說,則任何的風吹草動,都可以喚醒。

而在計算機界,冬眠(Hibernate)時,會關閉整個系統的供電,因此想醒來,唯有Power按鈕可用。而睡眠時,為了縮短Wakeup時間,并不會關閉所有的供電,另外,為了較好的用戶體驗,通常會保留某些重要設備的供電(如鍵盤),那樣這些設備就可以喚醒系統。

這些刻意保留下來的、可以喚醒系統的設備,統稱為喚醒源(Wakeup source)。而Wakeup source的選擇,則是PM設計工作(特別是Sleep、Standby等功能)的重點。

3. 軟件架構及模塊匯整

3.1 軟件架構

內核中該部分的軟件架構大概可以分為三個層次,如下圖:

0

1)API Layer,描述用戶空間API的一個抽象層。

這里的API有兩類,一類涉及Hibernate和Sleep兩個功能(global APIs),包括實際功能、測試用功能、Debug用功能等,通過sysfs和debugfs兩種形式提供;另一類是Hibernate特有的(STD APIs),通過sysfs和字符設備兩種形式提供。

2)PM Core,電源管理的核心邏輯層,位于kernel/power/目錄下,包括主功能(main)、STD、STR&Standby以及輔助功能(assistant)等多個子模塊。

主功能,主要負責實現global APIs相關的邏輯,為用戶空間提供相應的API;

STD,包括hibernate、snapshot、swap、block_io等子模塊,負責實現STD功能和硬件無關的邏輯;

STR&Stanby,包括suspend和suspend_test兩個子模塊,負責實現STR、Standby等功能和硬件無關的邏輯。

3)PM Driver,電源管理驅動層,涉及體系結構無關驅動、體系結構有關驅動、設備模型以及各個設備驅動等多個軟件模塊。

3.2 用戶空間接口

3.2.1 /sys/power/state

state是sysfs中一個文件,為PM的核心接口,在“kernel/power/main.c”中實現,用于將系統置于指定的Power State(供電模式,如Hibernate、Sleep、Standby等)。不同的電源管理功能,在底層的實現,就是在不同Power State之間切換。

讀取該文件,返回當前系統支持的Power State,形式為字符串。在內核中,有兩種類型的Power State,一種是Hibernate相關的,名稱為“disk”,除“disk”之外,內核在"kernel/power/suspend.c"中通過數組的形式定義了另外3個state,如下:

1: const char *const pm_states[PM_SUSPEND_MAX] = { ? 2: ? ? ? ? [PM_SUSPEND_FREEZE] ? ? = "freeze", ? 3: ? ? ? ? [PM_SUSPEND_STANDBY] ? ?= "standby", ? 4: ? ? ? ? [PM_SUSPEND_MEM] ? ? ? ?= "mem", ? 5: };

這些Power State的解釋如下:

▆ freeze

這種Power State,并不涉及具體的Hardware或Driver,只是凍結所有的進程,包括用戶空間進程及內核線程。和我們熟知的“冬眠”和“睡眠”相比,就稱為“閉目養神”吧(可想而知,能節省的能量是有限的)。

【注:我們在之前的描述中,并沒有特別描述該State,因為它在較早的內核中,只是Sleep、Hibernate等功能的一部分,只是在近期才獨立出來。另外一個原因是,該state的省電效果不是很理想,所以其引用場景也是有限的。】

▆ standby,即第2章所描述的Standby狀態。

▆ mem,即通常所講的Sleep功能,也是第2章所描述的STR,Suspend to RAM。

▆ disk,即Hibernate功能,也是第2章所描述的STD,Suspend to Disk。

寫入特定的Power State字符串,將會把系統置為該模式。

3.2.2 /sys/power/pm_trace

PM Trace用于提供電源管理過程中的Trace記錄,由“CONFIG_PM_TRACE”宏定義(kernel/power/Kconfig)控制是否編譯進內核,并由“/sys/power/pm_trace”文件在運行時控制是否使能該功能。

3.2.3 /sys/power/pm_test

PM test用于對電源管理功能的測試,由“CONFIG_PM_DEBUG”宏定義(kernel/power/Kconfig)控制是否編譯進內核。其核心思想是:

▆ 將電源管理過程按照先后順序,劃分為多個步驟,如core、platform、devices等。這些步驟稱作PM Test Level。

▆ 系統通過一個全局變量(pm_test_level),保存系統當前的PM Test Level。該變量的值可以通過”/sys/power/pm_test“文件獲取及修改。

▆ 在每一個電源管理步驟結束后,插入PM test代碼,該代碼以當前執行步驟為參數,會判斷當前的PM Test Level和執行步驟是否一致,如果一致,則說明該步驟執行成功。出于Test考量,執行成功后,系統會打印Test信息,并在等待一段時間后,退出PM過程。

▆ 開發人員可以通過修改全局的Test Level,有目的測試所關心的步驟是否執行成功。

上面已經講了,該文件用于獲取及修改PM Test Level,具體的Level信息在“kernel/power/main.c”中定義,格式如下(具體的意義,比較簡單,對著相關的代碼看,非常清晰,這里就不啰嗦了):

1: static const char * const pm_tests[__TEST_AFTER_LAST] = { ? 2: ? ? ? ? [TEST_NONE] = "none", ? 3: ? ? ? ? [TEST_CORE] = "core", ? 4: ? ? ? ? [TEST_CPUS] = "processors", ? 5: ? ? ? ? [TEST_PLATFORM] = "platform", ? 6: ? ? ? ? [TEST_DEVICES] = "devices", ? 7: ? ? ? ? [TEST_FREEZER] = "freezer", ? 8: };

3.2.4 /sys/power/wakeup_count

該接口只和Sleep功能有關,因此由“CONFIG_PM_SLEEP”宏定義(kernel/power/Kconfig)控制。它的存在,是為了解決Sleep和Wakeup之間的同步問題。

我們知道,系統睡眠后,可以通過保留的Wakeup source喚醒系統。而在當今的CPU體系中,喚醒系統就是喚醒CPU,而喚醒CPU的唯一途徑,就是Wakeup source產生中斷(內核稱作Wakeup event)。而內核要保證在多種狀態下,Sleep/Wakeup的行為都能正常,如下:

▆ 系統處于sleep狀態時,產生了Wakeup event。此時應該直接喚醒系統。這一點沒有問題。

▆ 系統在進入sleep的過程中,產生了Wakeup event。此時應該放棄進入sleep。

這一點就不那么容易做到了。例如,當Wakeup event發生在“/sys/power/state”被寫之后、內核執行freeze操作之前。此時用戶空間程序依舊可以處理Wakeup event,或者只是部分處理。而內核卻以為該Event已經被處理,因此并不會放棄此次sleep動作。

這就會造成,Wakeup event發生后,用戶空間程序已經后悔了,不想睡了,但最終還是睡下去了。直到下一個Wakeup event到來。

為了解決上面的問題,內核提供wkaeup_count機制,配合“/sys/power/state”,以實現Sleep過程中的同步。該機制的操作行為如下:

▆ wakeup_count是內核用來保存當前wakeup event發生的計數。

▆ ?用戶空間程序在寫入state切換狀態之前,應先讀取wakeup_count并把獲得的count寫回給wakeup_count。

▆ 內核會比對寫回的count和當前的count是否一致,如果不一致,說明在讀取/寫回操作之間,產生了新的的wakeup event,內核就會返回錯誤。

▆ 用戶空間程序檢測到寫入錯誤之后,不能繼續后的動作,需要處理響應的event并伺機再次讀取/寫回wakeup_count。

▆ 如果內核比對一致,會記錄write wakeup_count成功時的event快照,后面繼續suspend動作時,會檢查是否和快照相符,如果不符,會終止suspend。

▆ 用戶空間程序檢測到寫入正確后,可以繼續對state的寫入,以便發起一次狀態切換。而此時是安全的。

3.2.6 /sys/power/image_size

該接口也是STD特有的。我們知道,STD的原理是將當前的運行上下文保存在系統的disk(如NAND Flash,如硬盤),然后選擇合適的方式關閉或重啟系統。保存上下文是需要存儲空間的,不光是disk中的存儲空間,也包括位于內存的用于交換或緩沖的空間。

而該接口,就是設置或者獲取當前內存中需要分配多少空間,用于緩沖需要寫入到disk的數據。單位為byte。

3.2.7 /sys/power/reserverd_size

reserverd_size用于指示預留多少內存空間,用于在->freeze() 和 ->freeze_noirq()過程中保存設備驅動分配的空間。以免在STD的過程中丟失。

3.2.8 /sys/power/resume

該接口也是STD特有的。正常情況下,在重新開機后,內核會在后期的初始化過程中,讀取保存在disk中的image,并恢復系統。而該接口,提供了一種在用戶空間手動的讀取image并恢復系統的方法。

通常情況下,該操作出現在系統正常運行的過程中,需要加載并執行另外的image。

3.2.9 debugfs/suspend_status

該接口是以debugfs的形式,向用戶空間提供suspend過程的統計信息,包括:成功的次數、失敗的次數、freeze失敗的次數等等。

3.2.10 /dev/snapshot

該接口也是STD特有的。它通過字符設備的形式,向用戶空間提供software的STD操作。我們會在后續的文章中詳細描述。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/78285.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/78285.shtml
英文地址,請注明出處:http://en.pswp.cn/web/78285.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Spring 命名空間注入:p、c 與 .util 的深度解析

在 Spring 框架的開發過程中,XML 配置是一種常見且強大的方式來管理 Bean。為了讓配置更加簡潔、易讀,Spring 提供了多種命名空間注入的方法,其中 p 命名空間注入、c 命名空間注入和 .util 命名空間尤為重要。本文將詳細介紹這三種命名空間的…

RUST變量學習筆記

1,作用域概念 捕獲環境 2,所有權概念 Rust則是通過所有權和借用來保證內存安全。很多人不理解為啥說Rust是內存安全的,其實就是在默認情況下,你是寫不出內存不安全的代碼的。 Rust的所有權并不難理解,它有且只有如下…

探索 Spring AI 的 ChatClient API:構建智能對話應用的利器

探索 Spring AI 的 ChatClient API:構建智能對話應用的利器 前言 在當今人工智能蓬勃發展的時代,智能對話系統成為了眾多應用的核心組成部分。無論是客服機器人、智能助手還是聊天應用,都離不開高效、靈活的對話處理能力。Spring AI 作為 S…

開源ERP系統對比:Dolibarr、ERPNext與Odoo

對于尋求開源ERP解決方案的企業而言,Dolibarr、ERPNext和Odoo是三個備受關注的選擇。它們各自擁有獨特的優勢和特點,適用于不同規模和需求的組織。以下是對這三個系統的詳細介紹和對比,以幫助您更好地理解它們的差異,并結合中文支…

【2025年】MySQL面試題總結

文章目錄 1. MySQL 支持哪些存儲引擎?默認使?哪個?2. MyISAM 和 InnoDB 有什么區別?3. 事務的四大特性?4. 并發事務帶來了哪些問題?5. 不可重復讀和幻讀有什么區別?6. MySQL 事務隔離級別?默認是什么級別&#xff1…

Linux常用命令29——delgroup刪除組

在使用Linux或macOS日常開發中,熟悉一些基本的命令有助于提高工作效率,delgroup 是用于刪除用戶組的一個命令。此命令通常由超級用戶(root)運行,或者通過 sudo 提權來操作。本篇學習記錄delgroup命令的基本使用。 下面…

字節暑期實習-網絡運維工程師面經

崗位描述 這個是ByteIntern實習,是暑期實習崗位 崗位 一面 先自我介紹 抓項目技術(會進行確認是什么技術) TCP的三次握手和四次揮手 序列號和確認應答號的位置和大小 序列號是隨機的嗎? 序列號為什么是隨機的? …

5.3刷題

P3370 【模板】字符串哈希 #include<bits/stdc.h> using namespace std; #define int long long typedef unsigned long long ull; int n; ull myhash(string s){ull code 0, x 131, y 140814840257324663;for(int i 0; i < s.size(); i){code (code * x (ull)…

Kettle下載安裝教程

## 什么是Kettle Kettle&#xff08;現在也稱為Pentaho Data Integration&#xff0c;簡稱PDI&#xff09;是一款開源的ETL&#xff08;Extract-Transform-Load&#xff09;工具&#xff0c;用于數據抽取、轉換和加載。它允許用戶通過圖形化界面設計和執行數據集成流程&#xf…

FreeRtos實戰從入門到精通--任務創建和刪除(動態方法)--事了拂衣去,深藏功與名

FreeRtos是之前的一些聰明的工程師寫的免費且開源的嵌入式實時操作系統代碼&#xff0c;由于我們實際工作中不需要再去寫rtos&#xff0c;我們只需要用就行了&#xff0c;所以博主這里只分享項目工程實戰相關的內容&#xff0c;具體rtos源碼&#xff0c;可以無需理會&#xff0…

Java通用Mapper自定義方法

目錄 一、定義通用 Mapper 接口二、繼承通用 Mapper 實現自定義方法三、注冊自定義 Mapper 接口四、在實體類對應的 Mapper 接口中使用自定義方法五、實現自定義方法的 SQL 邏輯注解方式XML 映射文件方式六、使用自定義方法七、注意事項在 Java 持久層開發中,MyBatis 的通用 M…

Android WebRTC回聲消除

文章目錄 安卓可用的回聲消除手段各種回聲消除技術優缺點WebRTC回聲消除WebRTC回聲消除回聲消除處理流程WebRTC AECM APP 安卓可用的回聲消除手段 硬件回聲消除 使用 AudioRecord 的 VOICE_COMMUNICATION 模式&#xff1a;通過 AudioRecord 的 VOICE_COMMUNICATION 音頻源可以…

基于 SAFM 超分辨率上采樣模塊的 YOLOv12 改進方法—模糊場景目標檢測精度提升研究

在復雜視覺環境中,如低光照、霧天或遠距離拍攝等場景下,圖像質量下降導致目標模糊,使得傳統目標檢測模型難以實現高精度識別。YOLO系列作為主流單階段檢測框架,在速度和精度方面表現出色,但在模糊和小目標場景中仍存在性能瓶頸。本文提出一種面向 YOLOv12 的創新性改進方法…

Spring 事務的底層原理常見陷阱

一、Spring 事務的底層原理 1. 核心機制 動態代理&#xff08;AOP&#xff09;&#xff1a; Spring 通過動態代理&#xff08;JDK 或 CGLIB&#xff09;生成代理對象&#xff0c;攔截被 Transactional 注解標記的方法。事務攔截器&#xff1a; TransactionInterceptor 負責管…

Java SE(6)——類和對象(一)

1.初始面向對象 1.1 什么是面向對象 Java是一門純面向對象的編程語言(Object Oriented Program&#xff0c;簡稱OOP)&#xff0c;在面向對象的世界里&#xff0c;一切皆為對象。面向對象是解決問題的一種思想&#xff0c;主要依靠對象之間的交換來完成一件事情 1.2 面向過程…

cpp細碎知識點

1 重寫 (Override): 派生類中定義一個與基類虛函數具有相同函數簽名&#xff08;函數名、參數列表、返回類型&#xff09;的函數&#xff0c;這被稱為重寫。 重寫意味著派生類提供了基類虛函數的一個特定于派生類的實現。 重寫是實現多態的關鍵 2 虛基類 (Virtual Base Class…

若依 FastAPI + Vue3 項目 Docker 部署筆記( 啟動器打包教程)

本文記錄了將 start.bat 打包成 .exe 啟動器的詳細教程&#xff0c;適合項目交付或導師演示用。 &#x1f9ed; 一、如何將 start.bat 打包為啟動器 .exe&#xff08;含圖標 自動打開瀏覽器&#xff09; ? 1. 創建三大功能腳本 start.bat → 啟動項目&#xff08;docke…

基于springboot的金院銀行廳預約系統的設計及實現(源碼+lw+部署文檔+講解),源碼可白嫖!

摘要 隨著信息技術在管理上越來越深入而廣泛的應用&#xff0c;信息管理系統的實施在技術上已逐步成熟。信息管理系統是一個不斷發展的新型學科&#xff0c;任何一個單位要生存要發展&#xff0c;要高效率地把內部活動有機地組織起來&#xff0c;就必須建立與自身特點相適應的…

創意控制臺:下雨動畫特效(ASCII 雨滴下落)

在編程的世界里&#xff0c;控制臺不僅僅是輸出文本信息的工具&#xff0c;通過巧妙的代碼設計&#xff0c;我們還能在其中創造出充滿趣味的動態畫面。本文將帶領大家使用 C 語言打造一個創意控制臺下雨動畫特效&#xff0c;利用 ASCII 字符模擬雨滴下落的過程&#xff0c;為單…

MySQL--索引入門

MySQL官方對索引的定義為&#xff1a;索引&#xff08;Index&#xff09;是幫助MySQL高效獲取數據的數據結構。 Mysql在存儲數據之外&#xff0c;數據庫系統各種還維護著滿足特定查找算法的數據結構&#xff0c;這些數據結構以某種引用&#xff08;指向&#xff09;表中的數據…