Linux的suspend機制的設計原理

2021-09-21 02:42:11 字數 1946 閱讀 5725

linux中實現了suspend-to-disk的機制,由pm_suspend_disk來完成,有網友問了乙個問題:smp在進入suspend(standby)模式的時候,各平台通用的電源管理**會先把除了引導cpu以外的其他cpu都關掉,然後引導cpu自己再進入睡眠。當睡眠結束的時候,引導cpu會從進入睡眠的地方繼續執行,而其他cpu則要重新啟動。我的疑問是,既然進入suspend狀態後,cpu可以保留休眠前的狀態。那麼為什麼不能讓非引導cpu也從休眠的地方繼續,而是要有個停掉和重啟的過程。這麼做有什麼特殊的考慮或者不這麼做有什麼難以克服的困難麼?

這個問題十分具有代表性,到底為什麼?我們不能靠理論獲得答案,我們通過閱讀linux源**可以得到一些啟示,在此先說一下大體的思想,其實在linux中並沒有不能怎麼樣,只有怎麼樣不好,難道就真的不能儲存所有的cpu的狀態,等待resume的時候再恢復嗎?其實完全可以,但是要想明白linux為什麼沒有這麼做,還是必須理解suspend的本質,如果真的不理解什麼是suspend,那麼看**或許是乙個簡單又快捷的方法了。其實suspend就是將機器的當前狀態儲存起來,然後休眠,這樣可以節省能源,狀態可以儲存在記憶體也可以儲存在磁碟,我們這裡討論儲存在磁碟的情形,實際上不看**也可以理解到,儲存在磁碟的情況下,使用者就不允許再寫磁碟了,因為寫磁碟可能會破壞機器suspend時儲存的狀態,既然如此,我們就可以拋開磁碟來討論了,首先看一下進入suspend的**:

int pm_suspend_disk(void)

既然到了這裡,我們離cpu的suspend的實質就差不遠了,記住,我們跟蹤這一趟主要是為了弄清除了啟動cpu之外的其它的cpu的行為,因此我們接著往下看:

static int prepare_processes(void)

接下來就看看disable_nonboot_cpus:

void disable_nonboot_cpus(void)

int cpu_down(unsigned int cpu)

上面函式有一句是if (cpu_online(cpu)),就是在等待這個cpu執行idle,那麼它要是執行了idle呢?因為在__stop_machine_run啟動的核心執行緒中已經將該cpu從online點陣圖中清除,再加上cpu_idle的**,這樣的話,cpu就要執行halt了,這就是所謂的「除了啟動cpu之外的別的cpu的停止」,這裡可以可能出,並不是真的停止了別的cpu,而只是執行了halt,至於halt的意義可就值得一番研究了,總的來說,halt狀態下的cpu只可以被中斷打斷,時鐘中斷是一種中斷,當然可以使cpu脫離halt,但是cpu如果是dead狀態的話還是不能將任務排程於其上,因此想讓cpu工作,必須將其狀態設定為不是dead,這就是resume的所用,你如我們晃一下滑鼠,那麼滑鼠中斷會喚醒啟動cpu,為何僅僅喚醒啟動cpu呢,因為在進入suspend的時候,啟動cpu的資訊已經被儲存了,喚醒了啟動cpu之後,resume函式進一步將其它的cpu從halt狀態喚醒就可以了,實際上看看2.6.21核心之後的nohz就可以知道,nohz確實節省了不少能源因為suspend的時候不用再接收毫無意義的時鐘中斷了,實際上正常執行的時候如果沒有任務被排程到這個cpu的佇列上,那麼也可以長期halt而不接收時鐘中斷。

解釋到這裡就可以明白,並不是不可以實現所有的cpu都儲存當前狀態然後等到resume的時候被恢復,而是這樣做的話很麻煩,因為使用者suspend機器的時候,各個cpu執行的上下文很不統一,有的在使用者空間,有的在核心空間,有的在執行中斷處理,如果儲存這些狀態的話很麻煩因此面臨兩個選擇,乙個是強制儲存乙個是等待其它的cpu進入到乙個無關緊要的idle狀態,權衡之後就會發現,後者是乙個很好又很高效的方法,因此核心就選用了後者,也就是上面實現的那些。以下是我的回答:而且,機器的suspend並沒有什麼大不了的,看看**就明白的,其它的cpu只是進入了play_dead函式從而進入了halt,halt還是可以被中斷喚醒的,所以說在smp中suspend,別的cpu並沒有真的關閉,而是進入了halt而已,可以說別的cpu還活著,等到resume的時候,只是啟動cpu執行resume,別的cpu只是簡單的設定一下狀態就可以了,這樣的實現很簡單

android 阻止進入suspend的原因查詢

private static final boolean debug true private static final boolean debug spew debug false 修改為 private static final boolean debug true private static...

Java執行緒stop和suspend的廢棄

jdk1.0定義了stop和suspend方法,stop用來直接終止執行緒,suspend會阻塞執行緒直到另乙個執行緒呼叫resume.stop和suspend都有一些共同的點 都試圖專橫的控制乙個給定了的執行緒的行為.從jdk1.2開始,這兩個方法都被棄用了.stop天生就不安全,而經驗告訴我們呢...

Java執行緒stop和suspend的廢棄

jdk1.0定義了stop和suspend方法,stop用來直接終止執行緒,suspend會阻塞執行緒直到另乙個執行緒呼叫resume.stop和suspend都有一些共同的點 都試圖專橫的控制乙個給定了的執行緒的行為.從jdk1.2開始,這兩個方法都被棄用了.stop天生就不安全,而經驗告訴我們呢...