"

在上篇文章中,我們知道操作系統的原理是:在任何時間內,CPU有且只有一個任務在運行。如果沒有一個任務在運行,CPU在做什麼的?

事實證明,這種情況非常普遍,對於大多數個人計算機來說,它實際上是常態:睡眠過程的進程,都在等待某些條件喚醒,而近100%的CPU時間正在這個神祕的“空閒任務”中。事實上,如果CPU一直忙於普通用戶,那通常是有問題的,或者是惡意軟件。

為了保持設計的一致性,OS開發人員創建了一個空閒任務,當沒有其他工作時,該任務將被安排運行。我們在Linux 啟動過程中已經看到,空閒任務是進程0,它是計算機首次打開時運行的第一條指令的直接後代。它在rest_init中 初始化,其中init_idle_bootup_task初始化空閒調度類

"

在上篇文章中,我們知道操作系統的原理是:在任何時間內,CPU有且只有一個任務在運行。如果沒有一個任務在運行,CPU在做什麼的?

事實證明,這種情況非常普遍,對於大多數個人計算機來說,它實際上是常態:睡眠過程的進程,都在等待某些條件喚醒,而近100%的CPU時間正在這個神祕的“空閒任務”中。事實上,如果CPU一直忙於普通用戶,那通常是有問題的,或者是惡意軟件。

為了保持設計的一致性,OS開發人員創建了一個空閒任務,當沒有其他工作時,該任務將被安排運行。我們在Linux 啟動過程中已經看到,空閒任務是進程0,它是計算機首次打開時運行的第一條指令的直接後代。它在rest_init中 初始化,其中init_idle_bootup_task初始化空閒調度類

空閒CPU在做什麼?

簡而言之,Linux支持不同的調度類,例如實時進程,常規用戶進程等。當選擇進程成為活動任務時,將按優先級順序查詢這些類。這樣,核反應堆控制代碼總是在Web瀏覽器之前運行。但是,這些類通常會返回NULL,這意味著它們沒有合適的運行過程 - 它們都在睡覺。但是最後運行的空閒調度類永遠不會失敗:它總是返回空閒任務。

這一切都很好,但讓我們來看看這個空閒任務究竟在做什麼。cpu_idle_loop,由開源提供:

cpu_idle_loop


while(1){ while(!need_resched()){ cpuidle_idle_call(); }

/ *
[注意:切換到其他任務。當
再次選擇空閒任務運行時,我們將返回此循環。]
* /
schedule_preempt_disabled();
}

我已經省略了很多細節,我們稍後會仔細研究任務切換,但是如果你閱讀了代碼,你會得到它的要點:只要不需要重新安排,意味著改變活動任務,留下來閒。以經過的時間來衡量,這個循環及其在其他操作系統中的表兄弟可能是計算曆史中執行最多的代碼片段。對於英特爾處理器,傳統上保持空閒意味著運行暫停指令:

native_halt

static inline void native_halt(void)
{
asm volatile("hlt": : :"memory");
}

hlt停止處理器中的代碼執行並將其置於暫停狀態。奇怪的是,全世界數以百萬計的類似英特爾的CPU正在花費大部分時間停止工作,即使在他們通電的情況下也是如此。它也不是非常有效,能源明智,這導致芯片製造商為處理器開發更深層次的睡眠狀態,從而在更長的喚醒延遲中消耗更少的功耗。內核的cpuidle子系統負責利用這些節能模式。

現在,一旦我們告訴CPU停止或睡眠,我們需要以某種方式讓它恢復生機。如果您已閱讀上一篇文章,您可能會懷疑涉及到中斷,實際上它們也是如此。中斷會刺激CPU退出暫停狀態並恢復運行。所以把這些放在一起,這是你的系統在閱讀完全呈現的網頁時所做的大部分工作:

"

在上篇文章中,我們知道操作系統的原理是:在任何時間內,CPU有且只有一個任務在運行。如果沒有一個任務在運行,CPU在做什麼的?

事實證明,這種情況非常普遍,對於大多數個人計算機來說,它實際上是常態:睡眠過程的進程,都在等待某些條件喚醒,而近100%的CPU時間正在這個神祕的“空閒任務”中。事實上,如果CPU一直忙於普通用戶,那通常是有問題的,或者是惡意軟件。

為了保持設計的一致性,OS開發人員創建了一個空閒任務,當沒有其他工作時,該任務將被安排運行。我們在Linux 啟動過程中已經看到,空閒任務是進程0,它是計算機首次打開時運行的第一條指令的直接後代。它在rest_init中 初始化,其中init_idle_bootup_task初始化空閒調度類

空閒CPU在做什麼?

簡而言之,Linux支持不同的調度類,例如實時進程,常規用戶進程等。當選擇進程成為活動任務時,將按優先級順序查詢這些類。這樣,核反應堆控制代碼總是在Web瀏覽器之前運行。但是,這些類通常會返回NULL,這意味著它們沒有合適的運行過程 - 它們都在睡覺。但是最後運行的空閒調度類永遠不會失敗:它總是返回空閒任務。

這一切都很好,但讓我們來看看這個空閒任務究竟在做什麼。cpu_idle_loop,由開源提供:

cpu_idle_loop


while(1){ while(!need_resched()){ cpuidle_idle_call(); }

/ *
[注意:切換到其他任務。當
再次選擇空閒任務運行時,我們將返回此循環。]
* /
schedule_preempt_disabled();
}

我已經省略了很多細節,我們稍後會仔細研究任務切換,但是如果你閱讀了代碼,你會得到它的要點:只要不需要重新安排,意味著改變活動任務,留下來閒。以經過的時間來衡量,這個循環及其在其他操作系統中的表兄弟可能是計算曆史中執行最多的代碼片段。對於英特爾處理器,傳統上保持空閒意味著運行暫停指令:

native_halt

static inline void native_halt(void)
{
asm volatile("hlt": : :"memory");
}

hlt停止處理器中的代碼執行並將其置於暫停狀態。奇怪的是,全世界數以百萬計的類似英特爾的CPU正在花費大部分時間停止工作,即使在他們通電的情況下也是如此。它也不是非常有效,能源明智,這導致芯片製造商為處理器開發更深層次的睡眠狀態,從而在更長的喚醒延遲中消耗更少的功耗。內核的cpuidle子系統負責利用這些節能模式。

現在,一旦我們告訴CPU停止或睡眠,我們需要以某種方式讓它恢復生機。如果您已閱讀上一篇文章,您可能會懷疑涉及到中斷,實際上它們也是如此。中斷會刺激CPU退出暫停狀態並恢復運行。所以把這些放在一起,這是你的系統在閱讀完全呈現的網頁時所做的大部分工作:

空閒CPU在做什麼?

除定時器中斷外的其他中斷也會使處理器再次運行。如果你點擊一個網頁就會發生這種情況,例如:你的鼠標發出一箇中斷,它的驅動程序處理它,突然一個進程可以運行,因為它有新的輸入。此時need_resched()返回true,並且啟動空閒任務以支持您的瀏覽器。

但是,本篇文章是非常發散思維。這是隨時間變化的空閒循環:

"

在上篇文章中,我們知道操作系統的原理是:在任何時間內,CPU有且只有一個任務在運行。如果沒有一個任務在運行,CPU在做什麼的?

事實證明,這種情況非常普遍,對於大多數個人計算機來說,它實際上是常態:睡眠過程的進程,都在等待某些條件喚醒,而近100%的CPU時間正在這個神祕的“空閒任務”中。事實上,如果CPU一直忙於普通用戶,那通常是有問題的,或者是惡意軟件。

為了保持設計的一致性,OS開發人員創建了一個空閒任務,當沒有其他工作時,該任務將被安排運行。我們在Linux 啟動過程中已經看到,空閒任務是進程0,它是計算機首次打開時運行的第一條指令的直接後代。它在rest_init中 初始化,其中init_idle_bootup_task初始化空閒調度類

空閒CPU在做什麼?

簡而言之,Linux支持不同的調度類,例如實時進程,常規用戶進程等。當選擇進程成為活動任務時,將按優先級順序查詢這些類。這樣,核反應堆控制代碼總是在Web瀏覽器之前運行。但是,這些類通常會返回NULL,這意味著它們沒有合適的運行過程 - 它們都在睡覺。但是最後運行的空閒調度類永遠不會失敗:它總是返回空閒任務。

這一切都很好,但讓我們來看看這個空閒任務究竟在做什麼。cpu_idle_loop,由開源提供:

cpu_idle_loop


while(1){ while(!need_resched()){ cpuidle_idle_call(); }

/ *
[注意:切換到其他任務。當
再次選擇空閒任務運行時,我們將返回此循環。]
* /
schedule_preempt_disabled();
}

我已經省略了很多細節,我們稍後會仔細研究任務切換,但是如果你閱讀了代碼,你會得到它的要點:只要不需要重新安排,意味著改變活動任務,留下來閒。以經過的時間來衡量,這個循環及其在其他操作系統中的表兄弟可能是計算曆史中執行最多的代碼片段。對於英特爾處理器,傳統上保持空閒意味著運行暫停指令:

native_halt

static inline void native_halt(void)
{
asm volatile("hlt": : :"memory");
}

hlt停止處理器中的代碼執行並將其置於暫停狀態。奇怪的是,全世界數以百萬計的類似英特爾的CPU正在花費大部分時間停止工作,即使在他們通電的情況下也是如此。它也不是非常有效,能源明智,這導致芯片製造商為處理器開發更深層次的睡眠狀態,從而在更長的喚醒延遲中消耗更少的功耗。內核的cpuidle子系統負責利用這些節能模式。

現在,一旦我們告訴CPU停止或睡眠,我們需要以某種方式讓它恢復生機。如果您已閱讀上一篇文章,您可能會懷疑涉及到中斷,實際上它們也是如此。中斷會刺激CPU退出暫停狀態並恢復運行。所以把這些放在一起,這是你的系統在閱讀完全呈現的網頁時所做的大部分工作:

空閒CPU在做什麼?

除定時器中斷外的其他中斷也會使處理器再次運行。如果你點擊一個網頁就會發生這種情況,例如:你的鼠標發出一箇中斷,它的驅動程序處理它,突然一個進程可以運行,因為它有新的輸入。此時need_resched()返回true,並且啟動空閒任務以支持您的瀏覽器。

但是,本篇文章是非常發散思維。這是隨時間變化的空閒循環:

空閒CPU在做什麼?

在這個例子中,內核將定時器中斷編程為每4毫秒(ms)發生一次。這是滴答期。這意味著我們每秒獲得250個滴答,因此滴答率滴答頻率為250 Hz。這是在英特爾處理器上運行的Linux的典型值,100赫茲是另一個人群的最愛。這在CONFIG_HZ構建內核時在選項中定義。

現在看起來對於空閒CPU來說看起來像是一項非常多的毫無意義的工作,而且確實如此。如果沒有來自外界的新鮮輸入,CPU將繼續陷入這種地獄般的小睡狀態,在您的筆記本電腦電池耗盡時,每秒鐘會被喚醒250次。如果這是在虛擬機中運行,我們將從主機CPU燒掉電源和有價值的週期。

這裡的解決方案是動態勾選,以便當CPU空閒時,定時器中斷被取消激活或重新編程,以便在內核知道將要工作的地方發生(例如,進程可能有一個定時器)在5秒內到期,所以我們不能睡過去)。這也稱為無滴答模式

最後,假設您在系統中有一個活動進程,例如長時間運行的CPU密集型任務。這幾乎與空閒系統完全相同:上述圖保持大致相同,只需將一個進程替換為空閒任務,圖片就是準確的。在那種情況下,每隔4毫秒中斷任務是沒有意義的:它只是操作系統抖動,從而減慢了你的工作量。Linux還可以在這個單進程場景​​中停止固定速率滴答,即所謂的自適應滴答模式。最終,固定速率蜱可能會消失完全。

這對於一個帖子來說已經足夠發散了。內核的空閒行為是操作系統難題的重要組成部分,它與我們將看到的其他情況非常相似,因此這有助於我們構建正在運行的內核的圖片。

"

相關推薦

推薦中...