Linux:上下文,程序上下文和中斷上下文概念,上下文切換
- 1. 上下文 context:(就是一個環境)
- 2. 程序上下文
-
- 2.1 程序上下文的三個部分:使用者級上下文、寄存器上下文以及系統級上下文
- 2.2 上下文切換
- 2.3 使用者态内陷核心态三種方式:系統調用,異常,中斷
- 2.4 cpu核心态的三種狀态:
- 3. 中斷上下文
-
- 3.1 中斷上下文概念:
-
- 3.1.1 定義
- 3.1.2 中斷上下文切換:
- 3.2 中斷上下文代碼中注意事項
-
- 3.2.1 不能-睡眠或者放棄CPU。
- 3.2.2 不能-嘗試獲得信号量
- 3.2.3 不能-執行耗時的任務
- 3.2.4 不能-通路使用者空間的虛拟位址
- 4. 上下文切換(核心角度看)
-
- 4.1 上下文切換定義
- 4.2 上下文切換過程
-
- 4.2.1 切換虛拟記憶體
- 4.2.2 切換處理器
- 4.3 搶占時機
- 4.4 使用者搶占
-
- 4.4.1 使用者搶占定義:
- 4.4.2 使用者搶占時機:
- 4.5 核心搶占
-
- 4.5.1 核心搶占前提--是排程安全的(程序沒有鎖)
- 4.5.2 核心搶占發生時機
1. 上下文 context:(就是一個環境)
上下文簡單說來就是一個環境,相對于程序而言,就是程序執行時的環境。
具體來說就是各個變量和資料,包括所有的寄存器變量、程序打開的檔案、記憶體資訊等。
2. 程序上下文
可以說:
當一個程序在執行時,CPU的所有寄存器中的值、程序的狀态以及堆棧中的内容被稱為該程序的上下文。
也可以說:
所謂的“程序上下文”,可以看作是使用者程序傳遞給核心的這些參數以及核心要儲存的那一整套的變量和寄存器值和當時的環境等。
程序切換:
當核心需要切換到另一個程序時,它需要儲存目前程序的 所有狀态,
即儲存目前程序的上下文,以便在再次執行該程序時,能夠必得到切換時的狀态執行下去。
2.1 程序上下文的三個部分:使用者級上下文、寄存器上下文以及系統級上下文
一個程序的上下文可以分為三個部分:使用者級上下文、寄存器上下文以及系統級上下文。
- 使用者級上下文: 正文、資料、使用者堆棧以及共享存儲區;
- 寄存器上下文: 通用寄存器、程式寄存器(IP)、處理器狀态寄存器(EFLAGS)、棧指針(ESP);
- 系統級上下文: 程序控制塊task_struct、記憶體管理資訊(mm_struct、vm_area_struct、pgd、pte)、核心棧。
2.2 上下文切換
當發生程序排程時,進行程序切換就是上下文切換(context switch)。
作業系統必須對上面提到的全部資訊進行切換,新排程的程序才能運作。
2.3 使用者态内陷核心态三種方式:系統調用,異常,中斷
系統調用:使用者态程序主動要求切換到核心态的一種方式
本質:相當于執行了一個中斷響應的過程,因為系統調用實際上最終是中斷機制實作的,
而異常和中斷的處理機制基本上也是一緻的
異常:(軟中斷)比如缺頁異常
異常: 程序發,核心收
中斷:外圍裝置的中斷 如 ctrl+c等
中斷: 硬體發,核心收
擴充:
中斷: 硬體/程序發,核心收
信号:核心發,程序收
2.4 cpu核心态的三種狀态:
程式在執行過程中通常有使用者态和核心态兩種狀态,
CPU對處于核心态根據上下文環境進一步細分,是以有了下面三種狀态:
1、核心态,運作于程序上下文,核心代表程序運作于核心空間;
2、核心态,運作于中斷上下文,核心代表硬體運作于核心空間;
3、使用者态,運作于使用者空間。
3. 中斷上下文
3.1 中斷上下文概念:
3.1.1 定義
硬體通過觸發信号,導緻核心調用中斷處理程式,進入核心空間。
這個過程中,硬體的一些變量和參數也要傳遞給核心,核心通過這些參數進行中斷處理。
“ 中斷上下文”,就是硬體傳遞過來的這些參數和核心需要儲存的一些其他環境(主要是目前被打斷執行的程序環境)
特點:
中斷上下文也稱原子上下文,該上下文中執行的代碼不可阻塞
3.1.2 中斷上下文切換:
在發生中斷時,核心就在被中斷程序的上下文中,在核心态下執行中斷服務例程。
但同時會保留所有需要用到的資源,以便中繼服務結束時能恢複被中斷程序 的執行。
3.2 中斷上下文代碼中注意事項
運作于程序上下文的核心代碼是可搶占的,但中斷上下文則會一直運作至結束,不會被搶占。
是以中斷處理程式代碼要受到一些限制,在中斷代碼中不能出現實作下面功能的代碼:
3.2.1 不能-睡眠或者放棄CPU。
因為核心在進入中斷之前會關閉程序排程,一旦睡眠或者放棄CPU,這時核心無法排程别的程序來執行,系統就會死掉。牢記:中斷服務子程式一定不能睡眠(或者阻塞)。
3.2.2 不能-嘗試獲得信号量
如果獲得不到信号量,代碼就會睡眠,導緻(1)中的結果。
3.2.3 不能-執行耗時的任務
中斷處理應該盡可能快,因為如果一個處理程式是IRQF_DISABLED類型,他執行的時候會禁止所有本地中斷線,而核心要響應大量服務和請求,中斷上下文占用CPU時間太長會嚴重影響系統功能。中斷處理程式的任務盡可能放在中斷下半部執行。
3.2.4 不能-通路使用者空間的虛拟位址
因為中斷運作在核心空間。
4. 上下文切換(核心角度看)
4.1 上下文切換定義
上下文切換,即從一個可執行程序切換到另一個可執行程序。
由 context_switch()函數負責處理。
4.2 上下文切換過程
每當一個新的程序被選出來準備投入運作的時候, schedule()就會調用該函數,它完成兩項基本的工作
4.2.1 切換虛拟記憶體
調用 switch_mm(),把虛拟記憶體從上一個程序映射切換到新程序中
4.2.2 切換處理器
調用 switch_to(),從上一個程序的處理器狀态切換到新程序的處理器狀态。
包括儲存、恢複棧資訊和寄存器資訊,以及其他任何與體系結構相關的狀态資訊。
4.3 搶占時機
每個程序都包含一個 need_resched 标志,用來表明是否需要重新執行一次排程。
當某個程序應該被搶占時, scheduler_tick()會設定這個标志;
當一個優先級高的程序進入可執行狀态時, try_to_wake_up()也會設定這個标志。
核心會檢查該标志(如傳回使用者空間以及從中斷傳回的時候),确認其被設定,
然會調用 schedule()來切換到一個新的程序。
4.4 使用者搶占
4.4.1 使用者搶占定義:
在從系統調用或者中斷處理程式傳回使用者空間時,如果 need_resched 标志被設定,會導緻 schedule()被調用,核心會選擇一個其他(更合适的)程序投入運作,即發生使用者搶占。
4.4.2 使用者搶占時機:
即使用者搶占發生在: 從系統調用傳回使用者空間時; 從中斷處理程式傳回使用者空間時
4.5 核心搶占
4.5.1 核心搶占前提–是排程安全的(程序沒有鎖)
Linux支援核心搶占,前提是重新排程是安全的。隻要程序沒有持有鎖,就是安全的。
具體實作就是
在每個程序的 thread_info 中引入 preempt_count 計數器,初試為0。
每當使用鎖的時候+1,釋放鎖的時候-1,當數值為0時,核心就可以搶占。
4.5.2 核心搶占發生時機
從中斷傳回核心空間時,核心會檢查need_resched和preempt_count的值,以決定是調用排程程式(核心搶占)還是傳回執行程序。如果核心中的程序被阻塞了,或者它顯式地調用了schedule(),核心搶占也會顯式地發生。
即核心搶占會發生在:
中斷處理程式正在執行,且傳回核心空間之前;
核心代碼再一次具有可搶占性的時候;
核心中的任務顯式調用schedule();
核心中的任務阻塞(這同樣也會導緻調用schedule());
參考:
https://www.cnblogs.com/hustcat/articles/1505618.html
https://blog.csdn.net/qq_38500662/article/details/80598486