進程切換分兩步:
1.切換頁目錄以使用新的地址空間
2.切換內核棧和硬件上下文
對于linux來說,線程和進程的最大區別就在于地址空間,對于線程切換,第1步是不需要做的,第2是進程和線程切換都要做的。
切換的性能消耗:
1、線程上下文切換和進程上下問切換一個最主要的區別是線程的切換虛擬內存空間依然是相同的,但是進程切換是不同的。這兩種上下文切換的處理都是通過操作系統內核來完成的。內核的這種切換過程伴隨的最顯著的性能損耗是將寄存器中的內容切換出。
2、另外一個隱藏的損耗是上下文的切換會擾亂處理器的緩存機制。簡單的說,一旦去切換上下文,處理器中所有已經緩存的內存地址一瞬間都作廢了。還有一個顯著的區別是當你改變虛擬內存空間的時候,處理的頁表緩沖(processor's Translation Lookaside Buffer (TLB))或者相當的神馬東西會被全部刷新,這將導致內存的訪問在一段時間內相當的低效。但是在線程的切換中,不會出現這個問題。
系統調用:處于進程上下文
系統調用是在進程上下文中,并沒有tasklet之類的延遲運行,系統調用本身可以休眠,這些可以參見內核代碼
雖然系統調用實與其他中斷實現有點類似,通過IDT表查找入口處理函數,但是系統調用與其他中斷最大的不同是,系統調用是代表當前進程執行的,所以current宏/task_struct是有意義的,這個休眠可以被喚醒
系統調用,異常,中斷(其中中斷是異步時鐘,異常時同步時鐘),也可以把系統調用成為異常
中斷上下文:在中斷中執行時依賴的環境,就是中斷上下文(不包括系統調用,是硬件中斷)
進程上下文:當一個進程在執行時,CPU的所有寄存器中的值、進程的狀態以及堆棧中的內容被稱為該進程的上下文
1、首先,這兩個上下文都處于內核空間。
2、其次,兩者的區別在于,進程上下文與當前執行進程密切相關,而中斷上下文在邏輯上與進程沒有關系。
進程上下文主要是異常處理程序和內核線程。內核之所以進入進程上下文是因為進程自身的一些工作需要在內核中做。例如,系統調用是為當前進程服務的,異常通常是處理進程導致的錯誤狀態等。所以在進程上下文中引用current是有意義的。
內核進入中斷上下文是因為中斷信號而導致的中斷處理或軟中斷。而中斷信號的發生是隨機的,中斷處理程序及軟中斷并不能事先預測發生中斷時當前運行的是哪個進程,所以在中斷上下文中引用current是可以的,但沒有意義。事實上,對于A進程希望等待的中斷信號,可能在B進程執行期間發生。例如,A進程啟動寫磁盤操作,A進程睡眠后現在時B進程在運行,當磁盤寫完后磁盤中斷信號打斷的是B進程,在中斷處理時會喚醒A進程。
上下文這個詞會讓人想到進程的CPU寄存器狀態,但好像進入進程上下文(異常處理系統調用)和進入中斷上下文(中斷處理),內核所做的工作沒有太大區別。所以,這兩個上下文的主要區別,我認為在于是否與進程相關。
運行于進程上下文的內核代碼是可搶占的,但中斷上下文則會一直運行至結束,不會被搶占。因此,內核會限制中斷上下文的工作,不允許其執行如下操作:
(1) 進入睡眠狀態或主動放棄CPU;
由于中斷上下文不屬于任何進程,它與current沒有任何關系(盡管此時current指向被中斷的進程),所以中斷上下文一旦睡眠或者放棄CPU,將無法被喚醒。所以也叫原子上下文(atomic context)。
(2) 占用互斥體;
為了保護中斷句柄臨界區資源,不能使用mutexes。如果獲得不到信號量,代碼就會睡眠,會產生和上面相同的情況,如果必須使用鎖,則使用spinlock。
(3) 執行耗時的任務;
新聞熱點
疑難解答