線程調度爲什麼比進程調度更少開銷?

線程調度爲什麼比進程調度更少開銷?

在對比進程調度與線程調度的開銷前,我們需要明白兩點:

  • 進程與線程的差異
  • 任務調度的開銷

進程與線程的差異

我們首先要明白,線程和進程有什麼關係?從概念上來講,線程是進程的一部分,只是任務調度相關的部分,所以我們才說,“線程是調度的最小單位”。進程擁有着資源,這些資源不屬於某一個特定線程,因爲所有線程共享進程擁有的資源,所以我們才說,“進程是資源分配的最小單位”。需要特別說明的是,Linux在線程與進程的實現上與概念上有少許差別,這個等下再討論。

進程與線程關係

所以,我們fork一個新的進程時,實際上“伴生”了一個線程,而這個唯一的線程,實際上代表了這個進程參與到任務調度。在執行的過程中,進程通過pthread_create創建了更多的線程,例如上圖中的線程2,線程n。此時,不管線程1,線程2,還是線程n,他們都代表了進程進行任務調度。

既然我們知道了進程與線程有什麼關係,那麼實際的linux內核是怎麼實現進程與線程的呢?

在linux中,不管進程還是線程,都用struct task_struct描述。

struct task_struct {
	...
	struct mm_struct *mm; /*內存資源*/
	...
}

既然都是用struct task_struct描述,那麼進程和線程的關係怎麼體現?資源指針!例如上面代碼塊描述的結構成員struct mm_struct *mm,這是一個指針,指向實際的內存資源。同一個進程內的所有線程,他們都使用相同的資源,只需要把對應的資源指針指向相同的地址。

Linux內核就好像淡化了“線程”的概念,每一個線程描述都是struct task_struct,他們都是一個獨立的“進程”,都有着自己的進程號,都參與任務調度,只不過指向相同的進程資源。

任務調度的開銷

既然我們知道了進程和線程在linux實現上的關係,我們再來分析,爲什麼說線程調度比進程調度開銷更小?

或許你有這樣的疑問,既然在linux實現上,線程都是獨立的struct task_struct,都參與任務調度,那這裏說的線程調度和進程調度怎麼區分?

我們不妨這樣定義:

線程調度:使用相同資源的`struct task_struct`之間的調度
進程調度:使用不同資源的`struct task_struct`之間的調度

基於這樣的定義,爲了方便分析問題,我們回顧一下任務調度的開銷主要有什麼?

1. CPU執行任務調度的開銷,主要是進程上下文切換的開銷
2. 任務調度後,CPU Cache/TLB不命中,導致缺頁中斷的開銷

對於第1點的開銷,不管是進程調度還是線程調度都是必須的,所以,兩者的差異體現在第2點。

再看回我們對“進程調度”和“線程調度”的定義,有沒覺得靈光一閃?既然線程調度的struct task_struct都使用相同的資源,是不是就意味着,我即使切換到了其他的線程,CPU Cache/TLB命中的概率會高很多?相反,進程調度使用的是不同的資源,每次換了個進程,就意味着原有的Cache就不適用了,沒命中,就觸發更多的缺頁中斷,開銷自然就更多。

所以,我們明白了,線程調度爲什麼比進程調度更少開銷。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章