一 Linux--多線程

線程線程的概念線程: 線程是OS能夠進行運算調度的基本單位 。線程是一個進程中的一個單一執行流,通俗地說,一個程序里的一個執行路線就叫做線程 。
可以知道的是,一個進程至少有一個執行線程,這個線程就是主執行流 。一個進程的多個執行流是共享進程地址空間內的資源,也就是說進程的資源被合理分配給了每一個執行流 , 這些樣就形成了線程執行流 。所以說線程在進程內部運行,本質是在進程地址空間內運行 。需要注意的是 , Linux下沒有真正意義上的線程,線程是通過進程來模擬實現的 。這句話如何理解?
Linux系統下,沒有專門為線程設計相關的數據結構 。那線程又是如何被創建的呢?我們知道 , 創建一個進程,我們需要為它創建相關的數據結構,如:PCB(task_struct)、mm_sturct、頁表和file_struct等 。線程的創建和進程的創建是一樣的,線程也是創建一個一個的PCB,因為線程是共享進程地址空間的,所以這些線程都維護同一個進程地址空間 。
這樣可以看出一個線程就是一個執行流,每一個線程有一個task_struct的結構體,和進程一樣 , 這些task_struct都是由OS進行調度 。可以看出在CPU看來 , 進程和線程是沒有區別的,所以說Linux下的線程是通過進程模擬實現的 。

一 Linux--多線程

文章插圖
繼續思考,CPU如何區分Linux下的線程和進程?
其實CPU不需要考慮這個問題 , 在它眼中,進程和線程是沒有區別的 , 都是一個一個的task_struct,CPU只管負責調度即可 。
那如何理解我們之前所學的進程?
我們都知道 , 進程是承擔分配系統資源的基本實體,曾經CPU看到的PCB是一個完整的進程,也就是只有一個執行流的進程 ?,F在看到的PCB不一定是完整的進程,可能是一個進程的執行流總的一個分支,也就是多執行流進程 。所以說,現在CPU眼中,看到的PCB比傳統的進程更加輕量化了 。這種有多執行流的進程中的每一個執行流都可以看作是一個輕量級進程 。總結地說,線程是輕量級進程 ??偨Y:
簡單點來說,每個線程都有自己的PCB,只不過這些PCB都維護和共享這同一塊虛擬空間(進程的虛擬空間 , 也就是進程的PCB),但是線程的PCB更輕量級,操作系統分配資源的時候是以進程那塊PCB為分配資源的最小單位,所以給進程分配的資源,屬于該進程的線程們都共享,而線程是操作系統調度的最小單位,操作系統不會區分線程和進程,在操作系統眼里都是一個個PCB,CPU調度的時候只負責調用PCB就行了 。
  • 實際上無論是創建進程的fork,還是創建線程的pthread_create,底層實現都是調用一個內核函數clone 。
    • 如果復制對方的地址空間,那么就產生出一個進程
    • 如果共享對方的地址空間,就產生一個線程
    • 可以更簡單的理解進程和線程的區別 , 進程的創建就類似于深拷貝 , 線程的創建就類似于淺拷貝 , 更有助于理解
Linux下的進程和線程進程: 承擔分配系統資源的實體線程: CPU調度的基本單位注意: 進程之間具有很強的獨立性,但是線程之間是會互相影響的
線程共享一部分進程數據,也有自己獨有的一部分數據:(每個線程都有屬于自己的PCB)
  • 線程ID
  • 一組寄存器(記錄上下文信息,任務狀態段)
  • 獨立的??臻g(用戶空間棧)
  • 信號屏蔽字
  • 調度優先級
  • errno(錯誤碼)
  • 處理器現場和棧指針(內核棧)
進程的多個線程共享同一地址空間 , 因此Text Segment、Data Segment都是共享的 。如果定義一個函數,在各線程中都可以調用 , 如果定義一個全局變量,在各線程中都可以訪問到,除此之外,各線程還共享以下進程資源和環境:
  • 文件描述符
  • 每種信號的處理方式
  • 當前工作目錄
  • 用戶ID和組ID
  • 共享.text(代碼段)  .data(數據段) .bss(未初始化數據段).heap(堆)
關系圖:
一 Linux--多線程

文章插圖
Linux線程控制POSIX線程庫