① 一文解析linux進程的睡眠和喚醒
在Linux中,進程的睡眠與喚醒是一個關鍵概念。當進程執行完時間片後,Linux內核會通過調度器選擇下一個進程,使之獲取CPU控制權。此外,進程也可以主動通過調用`schele()`函數釋放CPU控制權,使其他進程運行。當進程需要等待特定事件發生,如設備初始化完成或I/O操作結束時,它會進入睡眠狀態,從運行隊列移出,加入等待隊列。
Linux中的進程睡眠有兩種狀態:可中斷的睡眠與不可中斷的睡眠。可中斷的睡眠進程在滿足特定條件時被喚醒,如硬體中斷、系統資源釋放或信號傳遞。而不可中斷的睡眠狀態較為少見,主要用於進程必須等待特定事件,直到事件發生而不會被中斷。
Linux操作系統中,進程通常通過`schele()`函數進入睡眠狀態。程序首先存儲進程結構指針,然後使用`set_current_state()`將進程狀態從執行狀態改為睡眠狀態。如果`schele()`被處於睡眠狀態的進程調用,進程將從運行隊列中移出。要喚醒睡眠中的進程,可以使用`wake_up_process()`函數,這將改變進程狀態並將其加入運行隊列,等待下一次調度。
然而,進程有時可能因競爭條件而進入無效喚醒狀態,導致無限期睡眠。這個問題發生在進程檢查條件後,狀態未被改為睡眠狀態之前。解決方法是將判斷條件與狀態更改合並為一個步驟,消除競爭條件,確保喚醒過程有效。
為了在Linux內核中避免無效喚醒,應使用特定的內核函數進行進程睡眠。例如,`DECLARE_WAITQUEUE()`用於創建等待隊列的項,`add_wait_queue()`將進程加入等待隊列並更改狀態為可中斷狀態。然後,進程循環檢查條件,如果條件滿足,設置狀態為運行狀態並移出等待隊列。若條件未滿足,調用`schele()`使進程重新調度。這種設計確保進程在條件滿足時能夠及時退出睡眠狀態,避免無效喚醒。
在Linux內核中,代碼示例展示了如何通過合理設計避免無效喚醒。通過在檢查條件之前設置進程狀態為睡眠狀態,確保即使在條件滿足時進程也不會錯誤地進入睡眠,從而有效避免了無效喚醒問題。
原文作者:Linux內核那些事
參考資源:內核技術中文網 - 構建全國最權威的內核技術交流分享論壇
② 一文了解Linux內核延時機制
內核延時機制是Linux系統中實現時間延時的兩種主要方式:忙等待與睡眠等待。忙等待適用於毫秒以內的精確延時,通過CPU佔用循環來實現,適用於對延遲時間要求不甚精確的場景,能夠充分利用CPU資源,提升系統吞吐性能。睡眠等待則適用於毫秒以上的長延時,將進程掛起並釋放CPU資源,底層實現通過系統定時器和等待隊列來完成。
內核提供了幾個用於實現納秒、微秒和毫秒級延時的函數,其原理實質上是忙等待。這些函數根據CPU頻率執行一定次數的循環。為更直觀地實現延遲,可以使用jiffies比較機制,通過比較當前jiffies與目標jiffies(即當前jiffies加上時間間隔的jiffies)來達到延時目的。
對於短延時,內核提供了sleep類、schele類、以及sleep_on類延時函數。sleep類函數使進程睡眠指定時間,受系統HZ和進程調度影響,msleep()、ssleep()不能被打斷,而msleep_interruptible()可以被打斷。schele類函數使用定時器原理實現進程睡眠,而sleep_on類函數則允許進程在等待隊列上睡眠,當超時發生時,進程將被喚醒。
總結而言,內核延時機制通過忙等待與睡眠等待兩種方式,提供了靈活多樣的延時手段,滿足不同場景的需求,同時兼顧了對系統資源的高效利用。
③ Linux-搶占式調度
主動調度機制在Linux中,是指進程在運行過程中,由於等待I/O操作或其他原因主動讓出CPU。所有進程的調用最終都會通過__schele函數來實現。與此同時,Linux系統也採用了搶占式調度來管理進程執行時間。當一個進程執行時間過長時,系統會判斷並決定切換到另一個進程,以確保系統資源的公平分配。衡量進程運行時間的依據是計算機內部的時鍾周期,通過時鍾中斷通知操作系統檢查是否到了需要搶占的時間點。
在Linux系統中,調度器主要通過scheler_tick函數來處理時鍾事件。該函數首先獲取當前CPU的運行隊列,然後找到正在執行的進程的task_struct。接著,它調用這個task_struct的調度類的task_tick函數,處理時鍾事件。對於普通進程,調度類通常為fair_sched_class,其處理時鍾事件的函數為task_tick_fair。
在task_tick_fair函數中,首先會查找當前進程對應的調度實體sched_entity和cfs_rq隊列,並調用entity_tick函數進行進一步處理。entity_tick函數更新當前進程的vruntime,並通過check_preempt_tick函數檢查是否到了搶占的時間。如果當前進程被喚醒且優先順序高於當前執行進程,就會觸發搶占。喚醒任務會被添加到隊列中,然後進行激活,其中調用check_preempt_curr函數檢查是否應該進行搶占。
用戶態和內核態的搶占時機對於進程調度至關重要。用戶態的搶占時機通常發生在系統調用返回時,此時會調用schele函數進行調度。內核態的搶占時機一般發生在preempt_enable函數中,該函數會關閉搶占以執行特定操作,當再次開啟時,就會提供內核態代碼被搶占的機會。
整個進程調度體系復雜且關鍵,涵蓋了主動調度、搶占式調度、時鍾事件處理、調度類調用、實體處理以及各種搶占時機的管理。通過深入了解這些機制,可以更好地理解Linux操作系統中進程調度的原理和實現。
④ Linux進程調度的概述
在Linux中,進程的運行時間不可能超過分配給他們的時間片,他們採用的是搶占式多任務處理,所回以進程之間的掛起和繼答續運行無需彼此之間的協作。
在一個如linux這樣的多任務系統中,多個程序可能會競爭使用同一個資源,在這種情況下,我們認為,執行短期的突發性工作並暫停運行以等待輸入的程序,要比持續佔用處理器以進行計算或不斷輪詢系統以查看是否有輸入到達的程序要更好。我們稱表現好的程序為nice程序,而且在某種意義上,這個nice 是可以被計算出來的。操作系統根據進程的nice值來決定它的優先順序,一個進程的nice值默認為0並將根據這個程序的表現不斷變化。長期不間斷運行的程序的優先順序一般會比較低。