概念
在學習操作系統的過程中,"進程"、"線程"概念其實很模糊。不同的上下文中,該名稱指代的概念很可能是不同的,概念的不清晰為學習和溝通帶來障礙,所以,在最開始我們先對齊概念。
很多書籍、文章裡會這樣來定義進程和線程:
- 進程:資源分配的最小單位;
- 線程:程序執行的最小單位;
其實這樣的描述依然是不夠具體的。
一個執行中的程序,其實是由一組資源和(一個或者多個)執行實體組成的,每個執行實體需要自己執行過程中所必須的獨有資源,所有的執行實體共享可共享資源。
這裡的執行實體,就是線程;這裡的執行實體和共享資源,就是進程。
進程中的資源
(用戶)虛擬地址空間
- 棧:(運行中的)局部變量、函數參數、返回地址等
- 堆:動態分配的內存
- BSS 段:未初始化或初始值為 0 的全局變量和靜態局部變量
- 數據段:已初始化且初始值非 0 的全局變量和靜態局部變量
- 代碼段:可執行代碼、字符串字面值、只讀變量
文件描述符(File Descriptor)
信號相關
- 信號處理程序設置(這個設置可以在每個線程中設置,但是整個進程的所有線程對該設置共享,以最後一次設置為準)
- 信號屏蔽設置
信號量(這裡的信號量跟上面的信號是兩碼事,上面的信號指的是中斷,這裡的信號量指的是進程間通信的一種機制)
上述的所有資源中,加粗標記的為每個線程中獨有的資源,未加粗的為所有線程共享的資源。
關於虛擬地址空間,這裡有張圖比較方便我們理解。這張圖的詳細解釋
很多文章中會提到以下幾個東西:
- 子進程
- 計數器和寄存器
- 程序計數器(PC)
- 寄存器
- 指令寄存器(IR)
- 地址寄存器
這其中,進程關係在 Linux 中其實是使用獨立的結構體進行存儲的,通過內核提供的方法來獲取,本質上不應該算是某種資源。其主體是內核 task_struct,後續我們會展開詳細描述。
而計數器和寄存器是體系結構相關的硬件實現,處於執行中的執行實體(線程)會使用這些硬件,所以也不能算是某種資源。
Linux 對進程和線程的實現(5.0.0 內核)
Linux 只有一個結構體來描述進程/線程—— task_struct,該文件位於 /linux/include/linux/sched.h。
這一結構體中有字段指向/描述相關資源和相互之間的關係,因而,該結構體更應該認為是一個“線程結構體”,而“線程結構體”上的這些對於相關資源和相互之間關係的描述,則構成了“進程”。
閱讀更多 JAVA架構師之路 的文章