作業系統知識回顧(2)--程序與執行緒
在作業系統中,程序和執行緒是極為重要的概念,這篇文章主要總結了程序、執行緒的基本概念及程序的排程。
1. 程序
1.1 什麼是程序
程序(process
)是具有一定獨立功能的程式關於某個資料集合上的一次執行活動。在傳統 OS
中,程序是系統進行資源分配和排程的基本單位。程序是一個正在執行程式的例項,包括程式程式碼、程式計數器和暫存器的值以及系統資源(如開啟的檔案)等。
在某一瞬間,一個 CPU
中只能執行一個程序,它是在各個程序之間來回切換的,每個程序執行的速度也不確定。
程序和程式間的聯絡和區別如下:
- 程式是一段靜態的程式碼;程序是一個動態執行的過程;
- 程式是產生程序的基礎;程序是程式功能的體現;
- 程式的每次執行都構成了不同的程序,通過多次執行,一個程式可對應多個程序;通過呼叫關係,一個程序可包括多個程式;
1.2 程序的實現
為了實現程序,作業系統維護了一張程序表(結構陣列),每個程序佔用一個程序表項(程序控制塊 PCB
),它是程序存在的唯一標誌。該表項包含了程序狀態的重要資訊,包括程序識別符號、狀態、優先順序、程式計數器、堆疊指標、暫存器等;
對程序的管理就是對通過 PCB
的組織管理來實現的。由於儲存了在程序的狀態變化時的必要資訊,在中斷一個正在執行的程序,並在後來恢復時,就好像程序從未中斷過。它是支援多程序和提供多處理的關鍵。
1.3 程序的狀態及轉換
如下圖是程序的三種狀態的狀態圖。一個程序的三種狀態是:
- 執行態:程序正在佔用
CPU
執行; - 就緒態:程序處於準備執行狀態,已經獲得除
CPU
外的所有資源; - 阻塞態:程序由於等待某種外部事件而暫停執行,即使獲得
CPU
,也不能執行。
程序之間主要有四種轉換關係:
- 由執行態轉換為就緒態:在時間片用完後,不得不讓出
CPU
; - 由就緒態轉換為執行態:程序被排程,獲得處理機資源;
- 由阻塞態轉換為就緒態:程序的
I/O
請求完成; - 由執行態轉換為阻塞態:程序發出
I/O
請求;
2. 執行緒
2.1 什麼是執行緒
執行緒(thread
)是程序中的一條執行流程。在引入執行緒的作業系統中,程序是擁有資源的基本單位;而執行緒是 CPU
一個程序中可以有多個執行緒,多個執行緒可以併發執行,它們之間共享相同的地址空間。但如果一個執行緒崩潰,可能會導致其所屬程序的所有執行緒崩潰。
2.2 程序和執行緒的區別
- 排程性:傳統 OS 中,程序是排程和分派的基本單位,但在引入執行緒後,執行緒是排程和分派的基本單位;
- 併發性:在引入執行緒後,多個程序可以併發執行,一個程序中的多個執行緒也可以併發執行;
- 擁有資源:程序是擁有資源的基本單位,而執行緒本身並不擁有資源;
- 系統開銷:程序切換付出的系統開銷明顯大於執行緒;
2.3 執行緒實現的三種方式
有三種執行緒的實現方式:
- 使用者執行緒:使用者空間實現,由使用者執行緒庫管理;
- 核心執行緒:核心中實現,由作業系統管理;
- 輕量級程序:核心中實現,支援使用者執行緒;
使用者執行緒
使用者執行緒是把整個執行緒包放在使用者空間中,不依賴於作業系統的核心,所以它可以在不支援執行緒的作業系統上實現。可以用一組使用者級的執行緒函式庫來實現執行緒。
每個程序都需要私有的執行緒表,用來跟蹤記錄該程序中執行緒的狀態資訊,不過僅記錄每個執行緒的程式計數器、堆疊指標、暫存器和狀態等,該執行緒表由執行時系統管理。而且使用者執行緒的切換由執行緒庫函式來完成,不需要使用者態、核心態切換,所以執行緒排程速度特別快。另外,也允許每個程序都擁有自定義的執行緒排程演算法。
但如果一個執行緒發起系統呼叫而阻塞,儘管其他執行緒可以執行,但整個程序都會阻塞。當一個執行緒開始執行後,除非它主動較交出 CPU
,否則它所在的程序中的其他執行緒將無法執行。
核心執行緒
核心執行緒在作業系統的核心中實現,由核心來完成對執行緒的建立、終止和管理。
由於執行緒的建立、終止和切換通過系統呼叫執行,由核心完成的,其系統開銷比較大;
但在一個程序中,如果某個核心執行緒發起系統呼叫而被阻塞,並不會影響其他使用核心執行緒的執行;
輕量級程序
輕量級程序是核心支援的使用者執行緒。一個程序可以有一個或多個輕量級程序,每個輕量級程序由一個單獨的核心執行緒來支援。而輕量級程序內部可以對應多個使用者執行緒。
3. CPU 排程
3.1 排程概念
處理機排程是當有多個程序(執行緒)競爭 CPU
時,排程程式需要從從就緒佇列中挑選下一個佔用 CPU
執行的程序。
排程演算法是為了解決通過什麼樣的準則來挑選就緒對列中的哪一個程序來執行。在每次排程時需要決定在下一個 CPU
計算時將哪個程序交給 CPU
。
3.2 排程演算法
先來先服務演算法FCFS
根據程序進入就緒態的先後順序排列。當程序進入阻塞態或結束時,就緒佇列中的下一個程序佔用 CPU
。
實現簡單,但可能短程序排在長程序後面,導致平均等待時間波動較大。
短程序優先演算法SJF
選擇就緒佇列中執行時間最短的程序佔用 CPU
執行。
- 可搶佔系統改進:短剩餘時間優先演算法,即選擇剩餘執行時間最短的程序執行。
短程序優先演算法有最優的平均週轉時間,但連續的短程序可能會使長程序無法獲得 CPU
資源,導致飢餓;執行時間不可預估,並不可靠。
最高響應比優先演算法HRN
選擇就緒佇列中響應比最高的程序。它是基於短程序優先演算法的改進,它不允許搶佔,另外等待時間越長,響應比越高,可以避免長時間地等待。
R = (w+s)/s // 其中 w 為等待時間,s 為執行時間。
複製程式碼
時間片輪轉演算法RR
按時間片分配給程序執行。在輪轉中,每個程序分到執行 1/n
的時間,時間片結束時,按先來先服務演算法切換到下一個就緒程序,每隔 n-1
個時間片程序會再次執行。
如果時間片過大,程序等待時間過長,極限情況下會退化為先來先服務演算法;如果時間片過小,雖然反應迅速,但上下文切換開銷較大,會影響系統吞吐量。
多級反饋佇列演算法
就緒佇列被劃分為多個獨立的子佇列,而且每個佇列可以有自己的排程策略,在佇列之間可以設定優先順序,第一個佇列優先順序最高,其餘依次遞減。優先順序越高的佇列分配的時間片越短。
在執行時,程序在不同佇列間移動,如果程序在當前優先順序的時間片下沒有完成,則下降到低一優先順序的佇列,以此類推。只有當一個佇列為空時才會去執行下一個佇列中的程序。
這種演算法對於 CPU
密集型程序的優先順序下降很快,而 I/O
密集型程序停留在高優先順序。