Linux電源管理(3)_關機和重啟的過程

原文:Linux電源管理(3)_Generic PM之重新啟動過程

1.前言

在使用計算機的過程中,關機和重啟是最先學會的兩個操作。同樣,這兩個操作在Linux中也存在,可以關機和重啟。這就是這里要描述的對象。在Linux Kernel中,主流的關機和重新啟動都是通過“ reboot”系統調用(具體可參考kernel / sys.c)來實現的。另外,除了我們常用的shutdown和restart兩類操作之外,該系統調用也提供了其他的reboot方式,也會在這里一一說明。

2.內核支持的reboot方式

也許你會奇怪,reboot是重啟的意思,所以用它實現Restart是合理的,但怎么用它實現關機操作呢?答案是這樣的:關機之后,早晚也會開機啊!所以關機是一種特殊的重新啟動過程,只不過持續的時間有點長而已。所以,內核根據不同的表現方式,將重新啟動分成如下的幾種方式:

???????

   1: / *   2: * _reboot()系統調用接受的命令。   3: *   4: *重新啟動使用默認命令和模式重新啟動系統。   5: * HALT停止OS,并將系統控制權交給ROM監視器(如果有)。   6: * CAD_ON Ctrl-Alt-Del序列導致RESTART命令。   7: * CAD_OFF Ctrl-Alt-Del序列將SIGINT發送到初始化任務。   8: * POWER_OFF如果可能,請停止OS并從系統中斷開所有電源。   9: * RESTART2使用給定的命令字符串重新啟動系統。  10: * SW_SUSPEND使用軟件掛起的掛起系統(如果已編譯)。  11: * KEXEC使用先前加載的Linux內核重新啟動系統  12: * /  13:           14: #define LINUX_REBOOT_CMD_RESTART 0x01234567  15: #define LINUX_REBOOT_CMD_HALT 0xCDEF0123  16: #define LINUX_REBOOT_CMD_CAD_ON 0x89ABCDEF  17: #define LINUX_REBOOT_CMD_CAD_OFF 0x00000000  18: #define LINUX_REBOOT_CMD_POWER_OFF 0x4321FEDC  19: #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4  20: #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2  21: #define LINUX_REBOOT_CMD_KEXEC 0x4558454

操作類型

英文全稱/別名

功能描述

備注

RESTART

Restart

正常重啟系統,重新加載內核和用戶空間。

用戶最常用的重啟方式,等同于

reboot

命令。

HALT

Halt

停止操作系統,將控制權交給其他代碼(如 BIOS/UEFI 或監控程序)。

表現形式依賴具體硬件實現,可能完全斷電或進入低功耗狀態。

CAD_ON/CAD_OFF

Ctrl+Alt+Del On/Off

允許/禁止通過

Ctrl+Alt+Del

組合鍵觸發重啟(RESTART)。

需鍵盤驅動支持,默認行為由內核配置決定。

POWER_OFF

Power Off

正常關機,停止操作系統并切斷電源(ACPI 狀態

S5

)。

等同于

poweroff

命令,需硬件支持完全斷電。

RESTART2

Restart with Command

重啟時攜帶自定義字符串(

cmd

),傳遞給關注重啟事件的進程或機器相關代碼。

用途由設備廠商自定義(如安卓的恢復模式)。

SW_SUSPEND

Software Suspend

掛起到內存(Suspend-to-RAM)或磁盤(Hibernate),進入低功耗狀態。

依賴

CONFIG_SUSPEND

內核選項,詳見后續休眠專題。

KEXEC

Kernel Execute

跳過 BIOS/UEFI,直接重啟到預加載的其他內核鏡像(需

CONFIG_KEXEC

支持)。

用于快速內核熱替換或崩潰恢復(如

kexec -l

加載新內核)。

3.重新啟動相關的操作流程

在Linux操作系統中,可以通過重新啟動,停止,關閉電源等命令,啟動重新啟動,具體的操作流程如下:

一般的Linux操作系統,在用戶空間都提供了一些工具集合(如常在嵌入式系統使用的Busybox),這些工具集合包含了重新引導,停止和關機三個和重新引導相關的命令。

用戶空間程序通過reboot系統調用,進入內核空間,內核空間根據執行路徑的不同,提供了kernel_restart,kernel_halt和kernel_power_off三個處理函數,響應用空間的reboot請求這三個處理函數的處理流程大致相同,主要包括:向有關重新引導過程的進程發送通知事件;調用驅動程序核心模塊提供的接口,關閉所有的外部設備;調用驅動程序syscore模塊提供的接口,關閉系統核心;調用架構相關的處理函數,進行后續的處理;最后,調用計算機相關的接口,實現真正意義上的重新啟動另外,采用TTY模塊提供的Sysreq機制,內核提供了其他途徑的關機方法,如某些按鍵組合,向/ proc文件寫入命令等

4.重新啟動過程的內部動作和代碼分析

4.1重啟系統調用

重新啟動系統調用的實現位于“ kernel / sys.c”,其函數原型如下:???????

   1: SYSCALL_DEFINE4(reboot,int,magic1,int,magic2,unsigned  int,cmd,   2:                 void __user *,arg)reboot,該系統調用的名稱。magic1,magic2,兩個int類型的“魔力數”,用于防止誤操作。具體在“ include / uapi / linux / reboot.h”中定義,感興趣的同學可以去看看(話說這些數字還是蠻有意思的,例如Linus同學及其家人的生日就在里面,猜出來的可以在文章下面留言)。cmd,第2章所描繪的reboot方式。arg,其他的額外參數。

reboot系統調用的內部動作比較簡單:

1)確定調用者的用戶權限,如果不是超級用戶(superuser),則直接返回錯誤(這也是我們再用戶空間執行reboot,halt,poweroff等命令時,必須是root用戶的原因);

2)判斷預測的魔術數是否匹配,如果不匹配,直接返回錯誤。這樣就可以進行的防止誤動作發生;

3)調用reboot_pid_ns接口,檢查是否需要由該接口處理reboot請求。

4)如果是POWER_OFF命令,且沒有注冊電源關閉的機器處理函數(pm_power_off),把該命令轉換為HALT命令;

5)根據特定的cmd命令,執行具體的處理,包括,

? ? ? 如果是RESTART或RESTART2命令,調用kernel_restart。

? ? ? 如果是CAD_ON或CAD_OFF命令,更新C_A_D的值,則表示允許通過Ctrl + Alt + Del組合鍵重新啟動系統。

? ? ? 如果是HALT命令,調用kernel_halt。

? ? ? 如果是POWER_OFF命令,調用kernel_power_off。

? ? ? 如果是KEXEC命令,調用kernel_kexec接口

? ? ? 如果是SW_SUSPEND,則調用hibernate接口

6)返回上述的處理結果,系統調用結束。

4.2 kernel_restart,kernel_halt和kernel_power_off

1)調用kernel_xxx_prepare函數,進行重新啟動/停止/ power_off前的準備工作,包括,

? ? ? 調用blocking_notifier_call_chain接口,向關心reboot事件的進程,發送SYS_RESTART,SYS_HALT或SYS_POWER_OFF事件。并發送出去。

? ? ? 將系統狀態設置為相應的狀態(SYS_RESTART,SYS_HALT或SYS_POWER_OFF)。

? ? ? 調用usermodehelper_disable接口,禁止用戶模式輔助

? ? ? 調用device_shutdown,關閉所有的設備

2)如果是power_off,并且存在PM相關的power off prepare函數(pm_power_off_prepare),則調用該調用函數;

3)調用migrate_to_reboot_cpu接口,將當前的進程(任務)移到一個CPU上;

注2:對于多CPU的機器,無論由哪個CPU觸發了當前的系統調用,代碼都可以運行在任意的CPU上。這個接口將代碼分派到一個特定的CPU上,并禁止調度器分派代碼到其他CPU上。首先,這個接口被執行后,只有一個CPU在運行,用于完成后續的重新啟動動作。

4)調用syscore_shutdown接口,將系統核心器件關閉(例如中斷等);

5)調用printk以及kmsg_dump,向這個世界發出最后的聲音(打印日志);

6)最后,由machine-core的代碼,接管后續的處理。

4.3 device_shutdown

設備模型中和device_shutdown有關的邏輯包括:

1.每個設備(結構設備)都會保存該設備的驅動(結構設備驅動程序)指針,以及該設備所在的總線(結構總線類型)的指針

2.設備驅動中有一個名稱為“ shutdown”的某種函數,用于在device_shutdown時,關閉該設備

3.總線中也有一個名稱為“ shutdown”的某種函數,用于在device_shutdown時,關閉該設備

4.系統的所有設備,都存在于“ / sys / devices /”目錄下,而該目錄由名稱為“ devices_kset”的kset表示。kset中會使用一個鏈表保存其下所有的kobject(也即“ / sys / devices /”目錄下的所有設備)。”的最終結果就是,以“ devices_kset”為根目錄,將內核中所有的設備(以相應的kobject為代表),組織成一個樹狀結構

device_shutdown的實現,該接口位于“ drivers / base / core.c”中,執行邏輯如下。???????

   1: / **   2: * device_shutdown-在每個設備上調用-> shutdown()以關閉。   3: * /   4: 無效device_shutdown(void)   5: {   6:         結構設備* dev,* parent;   7:            8:          spin_lock(&devices_kset-> list_lock);   9:         / *  10:          *向后移動設備列表,依次關閉每個設備。  11:          *請注意,設備拔出事件也可能會開始拉  12:          *設備離線,即使系統正在關閉。  13:          * /  14:         while (!list_empty(&devices_kset->list)) {  15:                 dev = list_entry(devices_kset->list.prev, struct device,  16:                                 kobj.entry);  17:?  18:                 /*  19:                  * hold reference count of device's parent to  20:                  * prevent it from being freed because parent's  21:                  * lock is to be held  22:                  */  23:                 parent = get_device(dev->parent);  24:                 get_device(dev);  25:                 /*  26:                  * Make sure the device is off the kset list, in the  27:                  * event that dev->*->shutdown() doesn't remove it.  28:                  */  29:                 list_del_init(&dev->kobj.entry);  30:                 spin_unlock(&devices_kset->list_lock);  31:?  32:                 /* hold lock to avoid race with probe/release */  33:                 if (parent)  34:                         device_lock(parent);  35:                 device_lock(dev);  36:?  37:                 /* Don't allow any more runtime suspends */  38:                 pm_runtime_get_noresume(dev);  39:                 pm_runtime_barrier(dev);  40:?  41:                 if (dev->bus && dev->bus->shutdown) {  42:                         if (initcall_debug)  43:                                 dev_info(dev, "shutdown\n");  44:                         dev->bus->shutdown(dev);  45:                 } else if (dev->driver && dev->driver->shutdown) {  46:                         if (initcall_debug)  47:                                 dev_info(dev, "shutdown\n");  48:                         dev->driver->shutdown(dev);  49:                  }  50:?  51:                  device_unlock(dev);  52:                 如果(父母)  53:                          device_unlock(parent);  54:?  55:                  put_device(dev);  56:                  put_device(父);  57:?  58:                  spin_lock(&devices_kset-> list_lock);  59:          }  60:          spin_unlock(&devices_kset-> list_lock);  61:          async_synchronize_full();  62: }

4.4 system_core_shutdown

系統核心的關機和設備的關機類似,也是從一個鏈表中,遍歷所有的系統核心,并調用它的關機接口。

4.5 machine_restart,machine_halt和machine_power_off

雖然以machine_為預先命名,這三個接口卻是屬于架構相關的處理函數,如ARM。以ARM為例,它們在“ arch / arm / kernel / process.c”中實現,具體如下。

4.5.1機器重啟???????

   1: / *   2: *重新啟動要求輔助CPU停止執行任何活動   3: *,同時主CPU重置系統。具有單個CPU的系統可以   4: *使用soft_restart()作為其機器描述符的.restart鉤子,因為   5: *將導致唯一可用的CPU復位。具有多個CPU的系統必須   6: *提供硬件重新啟動實施,以確保所有CPU立即復位。   7: *這是必需的,以便在主CPU上復位后運行的任何代碼   8: *不必與其他CPU協調以確保它們仍然不處于運行狀態   9: *執行預重置代碼,并使用主CPU的代碼希望的RAM  10: *使用。實施這種協調基本上是不可能的。  11: * /  12: void machine_restart(char * cmd)  13: {  14:          smp_send_stop();  15:?  16:          arm_pm_restart(reboot_mode,cmd);  17:?  18:         / *給失敗的寬限期1s * /  19:          mdelay(1000);  20:?  21:         / *糟糕-平臺無法重新啟動。告訴用戶!* /  22:          printk(“重新啟動失敗-系統停止\ n”);  23:          local_irq_disable();  24:         而(1);  25: }

0)先轉述一下該接口的注釋;

對于多CPU的機器而言,重新啟動之前必須保證其他的CPU位于非活動狀態,由其中一個主CPU負責重新啟動動作。并且,必須實現一個基于硬件的重新啟動操作,以保證所有CPU同步重啟,這是設計的重點!

對于單CPU機器而言,就相對簡單了,可以直接用軟件reset的方式實現重啟。

1)調用smp_send_stop接口,確保其他CPU位于非活動狀態;

2)調用機器相關的重啟接口,實現真正的重啟。該接口是一個變量函數,由“ arch / arm / kernel / process.c”聲明,由具體的機器代碼實現。格式如下:

? ? ? void(* arm_pm_restart )(char str,const char * cmd)= null_restart;

? ? ? EXPORT_SYMBOL_GPL(arm_pm_restart);

3)等待1s;

4)如果沒有返回,則重啟成功,否則失敗,打印錯誤信息。

4.5.2 machine_halt

ARM的halt很簡單,就是將其他CPU停下來,并禁止當前CPU的中斷后,死循環!確實,中斷被禁止了,又死循環了,不halt才怪。代碼如下:???????

   1: / *   2: *停止僅要求輔助CPU停止執行任何操作   3: *活動(執行任務,處理中斷)。smp_send_stop()   4: *實現此目標。   5: * /   6: void machine_halt(void)   7: {   8:          smp_send_stop();   9:?  10:          local_irq_disable();  11:         而(1)  12: }

4.5.3 machine_power_off

power off動作和restart類似,即停止其他CPU,調用其他函數。power off的某些函數和restart類似,就不再說明了。

5.總結與思考

5.1建筑和機器的概念

本文是我們在分析Linux內核時第一次遇到架構和機器的概念,順便解釋一下。內核代碼中最常見的目錄結構就是:arch / xxx / mach-xxx /(例如arch / arm / mach-bcm /)。由該目錄結構可知,架構(簡稱arch)是指具體的體系結構,如ARM,X86等。機器呢,是指具體體系結構下的一個或多個的SOC,如bcm等。

5.2電源管理驅動(和reboot有關的部分)需要實現的內容

由上面的分析可知,在Reboot的過程中,大部分的邏輯是否內核處理的,具體的驅動程序需要關注2點即可:

1)實現各自的關機接口,以正確關閉對應的設備

2)實現機器相關的接口,以確保足夠的機器可以正確重啟或關閉電源

看來還是很簡單的

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

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

相關文章

C# 繼承詳解

繼承是面向對象程序設計(OOP)中的核心概念之一,它極大地增強了代碼的重用性、擴展性和維護性。本篇文章將詳細講解C#中的繼承機制,包括基礎概念、語法特法、多重繼承(通過接口實現)、繼承的規則和實際應用示…

SQLAlchemy 2.x 異步查詢方法比較

SQLAlchemy 2.x 異步查詢中常用的 結果處理方法速查表,包含方法說明、使用場景、返回類型及典型用途。 SQLAlchemy 查詢結果處理方法速查表(適用于 AsyncSession) 方法 說明 返回類型 示例 SQL 示例輸出 scalars().all() 獲取單列所有…

極客天成參與”AI助力智慧城市構建”主題演講暨招商引智專題推介活動

4月7日下午,北京極客天成科技有限公司參加了天津市河東區數據局舉辦的“AI賦能智慧城市構建”主題演講暨招商引智專題推介活動。 活動中,華為(天津)有限公司數字政府解決方案總監姜華庚圍繞“政務大模型賦能智慧城市建設”&#x…

理解 EKS CloudWatch Pod CPU Utilization 指標:與 `kubectl top` 及節點 CPU 的關系

在使用 AWS EKS 時,CloudWatch Container Insights 提供了豐富的容器級別監控指標,幫助我們深入了解應用的運行狀態。如下截圖中的 ContainerInsights pod_cpu_utilization 指標就是一個非常重要的維度。本文將詳細解釋這個指標的含義,并將其…

使用pip3安裝軟件包報錯`externally-managed-environment`的幾種解決方式

1、pip3安裝軟件包報錯 報錯externally-managed-environment的原因: 從 Python 3.11 開始引入了 PEP 668 規范,該規范限制了在系統級 Python 環境中使用 pip 安裝第三方包,以避免與系統包管理器(如 apt)產生沖突。 如…

spring security用戶退出

Spring security默認實現了用戶退出的功能,用戶退出主要考慮退出后會話如何管理以及跳轉到哪個頁面。HttpSecurity類提供了logout()方法開啟退出登錄的支持,默認觸發用戶退出操作的URL為“/logout”,用戶退出時同時也會清除Session等默認用戶…

愛普生SG2520HHN晶振數據中心服務器的理想解決方案

在當今數字化時代,數據中心作為海量數據存儲、處理與傳輸的核心樞紐,其服務器的高效穩定運行至關重要。服務器作為其核心設備,對時鐘信號的精度和穩定性提出了嚴苛要求——微小的時序誤差可能導致數據傳輸失敗或系統宕機。愛普生 SG2520HHN 差…

LeetCode 155題解 | 最小棧

最小棧 一、題目鏈接二、題目三、算法原理思路1:用一個變量存儲最小元素思路2:雙棧普通棧和最小棧 四、編寫代碼五、時間復雜度 一、題目鏈接 最小棧 二、題目 三、算法原理 棧用數組、鏈表實現都行,最主要的就是在能在常數時間內檢索到最…

es+kibana---集群部署

其實一般es要跑3個節點的,這樣才能做高可用,處理并發大,但是我這里只是一個pod mkdir -p /stroe/data/es es搭建: #【拉取鏡像】 #docker pull elasticsearch:6.8.7 #docker pull busybox:1.28 【導入鏡像】 docker load -i es.…

WPF常用技巧匯總 - Part 2

WPF常用技巧匯總-CSDN博客 主要用于記錄工作中發現的一些問題和常見的解決方法。 目錄 WPF常用技巧匯總-CSDN博客 1. DataGrid Tooltip - Multiple 2. DataGrid Tooltip - Cell值和ToolTip值一樣 3. DataGrid Tooltip - Cell值和ToolTip值不一樣 4. DataGrid - Ctrl A /…

uniapp打包apk如何實現版本更新

我們做的比較簡單,在后端設置版本號,并在uniapp的config.js中定義版本號,每次跟后端的進行對比,不一致的話就更新。 一、下載apk 主要代碼(下載安裝包,并進行安裝,一般得手動同意安裝&#xf…

局部和整體的關系

Prompt:為什么要研究局部和整體的關系呢?是因為很多情況下,局部就能表達出整體? 這是一個非常本質的問題,其實你已經接近數學和物理中“幾何本質”的核心了。我們研究局部和整體的關系,是因為:…

企業辦公協同平臺安全一體化生態入住技術架構與接口標準分析報告

全球組織數字化與智能化背景下 企業辦公協同平臺安全一體化生態入住技術架構與接口標準分析報告 一、背景與市場需求 市場規模與增量 根據Statista數據,全球協同辦公平臺市場規模預計從2023年的$480億增長至2027年的$900億,年復合增長率(CAG…

【2025最新面試八股常問知識點】HTTP1.0,HTTP1.1,HTTP2.0,HTTP3.0,HTTP的進化之路。

HTTP 超文本傳輸協議(英文:HyperText Transfer Protocol,縮寫:HTTP)是一種用于分布式、協作式和超媒體信息系統的應用層協議。設計HTTP最初的目的是為了提供一種發布和接收HTML頁面的方法。通過HTTP或者HTTPS協議請求的…

【算法練習】歸并排序和歸并分治

文章目錄 1.歸并排序1.1 遞歸版本1.2 非遞歸版本 2.歸并分治2.1 計算數組的小和2.2 計算翻轉對 1.歸并排序 歸并排序的核心步驟是: 拆分:將無序數組不斷對半拆分成小塊,直到每個小塊只剩一個元素(自然有序)。 合并&a…

域對齊是什么

域對齊(Domain Alignment)是在機器學習和計算機視覺等領域中常用的技術 定義 域對齊旨在將不同域(Domain)的數據映射到一個共同的特征空間中,使得來自不同域的數據在該空間中具有相似的分布。這里的“域”可以指代不…

【linux】git安裝、升級

git安裝、升級 一、快捷安裝版本2.18.0二、自定義版本安裝(安裝、升級)1、移除舊文件2、安裝所需依賴3、選擇指定版本4、解壓文件、編譯5、增加環境變量,驗證是否版本 三、升級 一、快捷安裝版本2.18.0 yum install git git --version二、自…

編程日志4.24

棧的鏈表基礎表示結構 #include<iostream> #include<stdexcept> using namespace std; //模板聲明&#xff0c;表明Stack類是一個通用的模板&#xff0c;可以用于存儲任何類型的元素T template<typename T> //棧的聲明 //Stack類的聲明&#xff0c;表示一…

《冰雪傳奇點卡版》:探索冰雪世界的傳奇旅程!

《冰雪傳奇點卡版》以“純凈打金”為核心&#xff0c;摒棄復雜付費坑&#xff0c;回歸經典傳奇玩法。以下從核心玩法、資源獲取、職業搭配、交易變現四維度展開&#xff0c;助你高效開啟冰雪傳奇之旅。 一、核玩法解析&#xff1a;如何高效獲取資源&#xff1f; 1. 職業定位與…

DeepClaude開源程序可以實現代碼生成、創作詩句以及內容創作等功能

一、軟件介紹 文末提供程序和源碼下載 DeepClaude開源程序是增強的 AI&#xff0c;可以實現代碼生成&#xff1a;DeepSeek r1 Claude 3.7 十四行詩 - 無與倫比的性能&#xff01;內容創作&#xff1a;DeepSeek r1 Gemini 2.5 Pro - 卓越的質量&#xff01;OpenAI 兼容。流媒…