進程
Linux的進程調度
CFS 完全公平調度算法
權重和nice值
- 權重:權重越大,分配的時間比例越大,就相當于進程的優先級越高。 進程的時間 = C P U 總時間 ? 進程的權重 / 就緒隊列所有進程權重之和 進程的時間 = CPU總時間 * 進程的權重/就緒隊列所有進程權重之和 進程的時間=CPU總時間?進程的權重/就緒隊列所有進程權重之和
- nice值:進程對外的編程接口中使用的是一個nice值,大小范圍是
(-20~19)
,數值越小優先級越大,意味著權重值越大,nice值和權重之間可以轉換的。一個進程每降低一個nice值,就能多獲得10% 的CPU時間。1024權重對應nice值為0,被稱為NICE_0_LOAD
。默認情況下,大多數進程的權重都是NICE_0_LOAD
虛擬時間
虛擬時間vruntime和實際時間(wtime)轉換公式如下:
v r u n t i m e = w t i m e ? ( N I C E _ 0 _ L O A D / w e i g h t ) vruntime = wtime * (NICE\_0\_LOAD / weight) vruntime=wtime?(NICE_0_LOAD/weight)?
CFS調度主要保證每個進程運行的虛擬時間一致即可。在選擇下一個即將運行的進程時,只需要找到虛擬時間最小的進程就行了
在運行隊列中用紅黑樹結構組織進程的調度實體,這里進程虛擬時間正是紅黑樹的key,這樣進程就以進程的虛擬時間被紅黑樹組織起來了。紅黑樹的最左子節點,就是虛擬時間最小的進程,隨著時間的推移進程會從紅黑樹的左邊跑到右,然后從右邊跑到左邊,
CFS調度進程
讓虛擬時間最小的進程最先運行, 一旦進程運行虛擬時間就會增加,最后盡量保證所有進程的虛擬時間相等,誰小了就要多運行,誰大了就要暫停運行。
僵尸進程及守護進程?
守護進程
守護進程就是在后臺運?,不與任何終端關聯的進程,?個守護進程的?進程是init進程通常情況下守護進程在系統啟動時就在運?,它們以root??運?,并能處理?些系統級的任務
孤?進程
如果?進程先退出,?進程還沒退出,那么?進程的?進程將變為init進程。(注:任何?個進程都必須有?進程)。孤?進程將被init進程(進程號為1)所收養,并由init進程對它們完成狀態收集?作。因此孤?進程并不會有什么危害
僵?進程
?進程??進程先結束,而?進程?沒有回收?進程,釋放?進程占?的資源,此時?進程將成為?個僵?進程。
?個進程在調?exit命令結束??的?命的時候,其實它并沒有真正的被銷毀, 而是留下?個稱為僵?進程(Zombie)的數據結構
在Linux進程的狀態中,僵?進程是?常特殊的?種,它已經放棄了?乎所有內存空間,沒有任何可執?代碼,也不能被調度,僅僅在進程列表中保留?個位置,記載該進程的退出狀態等信息供其他進程收集。
系統所能使?的進程號是有限的,如果?量的產?僵?進程,將因為沒有可?的進程號而導致系統不能產?新的進程。 此即為僵?進程的危害,應當避免。
??如何避免僵?進程?
-
?進程通過wait和waitpid等函數等待?進程結束,但是這會導致?進程掛起。
-
忽略SIGCHLD信號,這常?于并發服務器的性能的?個技巧
因為并發服務器常常fork很多?進程,?進程終結之后需要服務器進程去wait清理資源。如果將此信號的處理?式設為忽略,可讓內核把僵??進程轉交給init進程去處理,省去了?量僵?進程占?系統資源。
-
如果?進程很忙可以?signal函數為SIGCHLD注冊handler信號處理函數,在信號處理函數調?wait/waitpid等待?進程退出。
-
通過兩次調?fork。?進程?先調?fork創建?個?進程然后waitpid等待?進程退出,?進程再fork?個孫進程后退出。這樣?進程退出后會被?進程等待回收,而對于孫?進程其?進程已經退出所以孫進程成為?個孤?進程,孤?進程由init進程接管,孫進程結束后,init會等待回收。
?進程結束后為什么要進?僵?狀態**?**
設置僵?進程的?的是維護?進程的信息,?進程可能要取得?進程的退出狀態等信息。這些信息?少包括進程ID,進程的終?狀態,以及該進程使?的CPU時間,當?進程調?wait或waitpid時就可以得到這些信息。
僵?狀態是每個?進程必經的狀態嗎?
是的。 任何?個?進程(init除外)在exit()之后,并??上就消失掉,而是留下?個稱為僵?進程(Zombie)的數據結構,等待?進程處理。這是每個?進程在結束時都要經過的階段。如果?進程在exit()之后,?進程沒有來得及處理,這時?ps -aux命令就能看到?進程的狀態是“Z”。如果?進程能及時 處理,可能?ps -aux命令就來不及看到?進程的僵?狀態,但這并不等于?進程不經過僵?狀態。
僵尸進程不能將它看成是一個正常的進程,這個進程已經死亡了,用戶區資源已經被釋放了,只是還占用著一些內核資源(PCB)。 僵尸進程就相當于是一副已經腐爛只剩下骨頭的尸體。
僵尸進程的出現是由于這個已死亡的進程的父進程不作為造成的。
消滅僵尸進程的方法是,殺死這個僵尸進程的父進程,這樣僵尸進程的資源就被系統回收了。通過kill -9 僵尸進程PID的方式是不能消滅僵尸進程的,這個命令只對活著的進程有效,僵尸進程已經死了,鞭尸是不能解決問題的。
上下文切換?
CPU上下文切換
根據任務的不同,CPU 的上下文切換就可以分為幾個不同的場景,也就是進程上下文切換、線程上下文切換以及中斷上下文切換。
系統調用
系統調用過程中,不會涉及到虛擬內存等進程用戶態的資源,也不會切換進程。
- 進程上下文切換,是指從一個進程切換到另一個進程運行。
- 而系統調用過程中一直是同一個進程在運行。
所以,系統調用過程通常稱為特權模式切換,而不是上下文切換。
進程上下文切換
進程是由內核來管理和調度的,進程的切換只能發生在內核態。所以,進程的上下文不僅包括了虛擬內存、棧、全局變量等用戶空間的資源,還包括了內核堆棧、寄存器等內核空間的狀態。
因此,進程的上下文切換就比系統調用時多了一步:在保存當前進程的內核狀態和CPU寄存器之前,需要先把該進程的虛擬內存、棧等保存下來;而加載了下一進程的內核態后,還需要刷新進程的虛擬內存和用戶棧。(與系統調用的區別?)
線程上下文切換
- 前后兩個線程屬于不同進程。此時,因為資源不共享,所以切換過程就跟進程上下文切換是一樣。
- 前后兩個線程屬于同一個進程。此時,因為虛擬內存是共享的,所以在切換時,虛擬內存這些資源就保持不動,只需要切換線程的私有數據、寄存器等不共享的數據。
中斷上下文切換
為了快速響應硬件的事件,中斷處理會打斷進程的正常調度和執行,轉而調用中斷處理程序,響應設備事件。而在打斷其他進程時,就需要將進程當前的狀態保存下來,這樣在中斷結束后,進程仍然可以從原來的狀態恢復運行。
-
中斷上下文切換并不涉及到進程的用戶態。
-
所以,即便中斷過程打斷了一個正處在用戶態的進程,也不需要保存和恢復這個進程的虛擬內存、全局變量等用戶態資源。
-
中斷上下文,其實只包括內核態中斷服務程序執行所必需的狀態,包括CPU 寄存器、內核堆棧、硬件中斷參數等。
-
對同一個 CPU 來說,中斷處理比進程擁有更高的優先級
-
進程上下文切換一樣,中斷上下文切換也需要消耗CPU
參考:
極客時間