日期:2019/5/3
關鍵詞:操作系統;線程。
一、線程與進程
進程的特點:
- 資源所有權:進程對資源(內存、I/O通道、I/O設備、文件等)具有控制權。
- 調度/執行:進程是OS調度和分派的實體。
1.1 多線程模型
關鍵點:
- TCB控制塊:寄存器的值、程序計數器、棧指針、優先級等與線程相關的狀態信息。
- 所有線程共享進程的狀態和資源。例如,全局變量,文件描述符表。當一個線程以讀權限打開文件,其他線程也能讀取(無需重復open)
線程的優點:
- 創建或者終止線程時空效率高。(Unix中,創建線程比創建進程的時間快10倍)
- 線程切換比進程切換所花時間少。
- 通信效率高。進程需要內核介入才能通信。
二、線程模型分類
2大類:用戶級線程(User Level Thread)和內核級線程(Kernel Level Thread)。
2.1 ULT
ULT線程管理由應用程序完成,內核意識不到線程的存在。(通信、調度等通過線程庫實現)
ULT線程調度與進程調度的關系,也是ULT與KLT的本質區別。
初始狀態: 線程庫中:線程2運行 OS內核中:進程B運行 |
|
假設1:線程2進行了一個將會阻塞進程B的系統調用(例如IO操作)。那么: 內核把B阻塞,切換到另外一個進程。 但在線程庫的角度看來,線程2仍處於運行狀態。(但從CPU的角度看,不是真的運行) |
|
假設2:時鍾中斷到來,B用完其時間片,內核進行進程切換,B從運行轉為就緒。但在線程庫的角度看來,線程2仍處於運行狀態。 |
|
假設3:線程2運行到需要線程1執行某些動作的一個點。(例如,1負責數據輸入,2負責計算和輸出這種情況) 線程2阻塞,線程庫調度線程1運行。 |
總結:
- b-d的三種狀態其實都是a的過渡。
- 在b和c中,內核把控制權切換到進程B,線程2就會回復執行。
- 進程在執行線程庫代碼時可被中斷,在中斷時可能處於線程切換狀態。(進程被恢復時,才能完成線程切換)
ULT優點:
- 線程庫在用戶空間當中,線程切換不需要陷入內核。(節省2次上下文切換)
- 可以自定義線程調度算法。
- ULT可在任意OS中使用,不需要修改內核。
ULT缺點:
- 有一個ULT進行系統調用,那么所有線程都會阻塞。
- 純ULT策略,多線程的程序不能使用CPU的多核技術。(因為內核調度的是進程,所以在純ULT策略下,多線程並不是真的在並行)
2.2 KLT
純KLT下,線程管理由內核完成,應用級沒有線程管理的代碼(只提供API)。
如上圖4.5(b),此時內核的調度單位是線程,一個線程阻塞,其他線程仍然在真的執行(前提CPU是多核)。
但線程調度需要陷入內核,時間花銷更大。
一組對比實驗:
- Null Fork:創建、調度、執行和完成調用一個空過程的進程/線程的時間。(派生一個線程/進程的開銷)
- Signal-Wait:進程/線程給正在等待的進程/線程發信號,然后在某個條件上等待需要的時間。(完成一次同步的開銷)
2.3 ULT+KLT組合方式
三、Linux的線程和進程管理
3.1 Linux進程
Linux中的進程/任務由一個task_struct表示,它包含以下信息:
- 進程的狀態(執行、就緒、掛起、停止、僵死)
- 調度信息:一個進程可能是普通或實時的,並具有優先級,實時進程在普通進程之前調度。
- 標識符:PID,用戶標識符和組標識符。組標識符用於給一組進程指定資源訪問權。
- 進程通信:支持Unix SVR4通信。
- 鏈接:到達父子進程的鏈接。
- 時間和計時器:包括進程創建時刻和進程消耗CPU的時間總量。一個進程還可以有若干個間隔計時器,通過系統調用來定義,計時器滿,OS會給該進程發送一個信號。計時器可以只使用一次或者多次。
- 文件系統:包括被該進程打開的任何文件的指針和指向該進程當前目錄的指針。
- 地址空間:定義分配給該進程的虛擬地址空間。
- CPU專用上下文:寄存器、棧指針。
3.2 Linux線程
傳統Linux內核:
- 單線程進程,不支持多線程
- 多線程程序需要用戶線程庫實現(也就是純ULT策略),最著名的就是pthread庫了。(所以即使在多核CPU環境下,使用pthread庫寫的多線程排序時間效率上並不比單線程好,因為這種情況下CPU調度進程(在CPU看來這個進程只有一個線程),實際上就是多個線程輪流使用CPU的某個核)
現代Linux內核:
- 不區分進程和線程
- 提供內核級線程的實現
- 將ULT映射到內核級進程
- 組成一個用戶級進程的多個ULT則映射到共享同一個組ID的多個Linux內核進程上(這些進程可共享文件和內存等資源,使得同一個組的進程調度不需要上下文切換)。
fork底層是通過clone系統調用實現,將所有標志位清零。標志位如下:
當進行進程切換時,內核先檢查當前進程的頁目錄地址是否與被調度的進程相同。若相同,則他們共享一個地址空間,此時上下文切換僅僅是PC指針的跳轉。注意:clone可以使同一個進程組的克隆進程共享同一內存空間,但不能共享同一個用戶棧,每個clone進程都有獨立的棧。