操作系統必須全方位地管理計算機系統中運行的程序。因此,操作系統為正在運行的程序建立了一個管理實體——進程
進程是一個具有一定獨立功能的程序關於某個數據集合的一次運行活動,是操作系統進行資源分配和調度的一個獨立單位
OS應能管理與控制進程的執行、協調管理處理器、主存儲器等各類資源在進程間的使用
一個進程包括五個實體部分,分別是:
-
(OS管理運行程序的)數據結構P
-
(運行程序的)內存代碼C
-
(運行程序的)內存數據D
-
(運行程序的)通用寄存器信息R
-
(OS控制程序執行的)程序狀態字信息PSW
不同程序在不同數據集上運行:構成兩個無關進程
不同程序在相同數據集上運行:構成兩個共享數據的交往進程
相同代碼在不同數據集上運行:構成兩個共享代碼的無關進程(共享的代碼稱為可再入程序,它是純代碼的,在執行中不變化,如編輯器)
前述的程序與數據集均是內存級的。那么,在不同時段中針對同一個外存數據文件運行同一個外存程序文件,兩次運行構成兩個不同的進程,因為意味着完全不同的P、C、D、R、Psw。
進程的引入除了為應用程序提供了一個獨立的邏輯控制流,使得程序員以為自己的程序在執行過程中獨占擁有處理器;還為應用程序提供了一個私有的地址空間(虛擬地址空間),使得程序員以為自己的程序在執行過程中獨占擁有存儲器。
Intel架構下linux操作系統中的一個進程對應的虛擬地址空間映像如圖所示:
整個虛擬地址空間分為兩大部分:內核虛擬存儲空間(簡稱內核虛擬空間)和進程虛擬存儲空間(簡稱用戶空間)。
在采用虛擬存儲機制的系統中,每個程序的可執行目標文件在裝入時都被映射到相同的虛擬空間中。
進程的三態模型:
運行態指進程占有處理器運行,處於運行態的進程個數不能大於處理器個數
就緒態指進程具備運行條件等待處理器運行
等待態指進程由於等待資源、輸入輸出、信號等而不具備運行條件
(1)運行態→等待態:出現等待事件,如等待資源、I/O、信號
(2)等待態→就緒態:等待事件完成,如資源滿足、I/O結束、信號完成
(3)就緒態→運行態:處理器空閑時會選擇更高優先權進程搶占
(4)運行態→就緒態:運行時間片到、有更高優先權進程
OS無法預期進程的數目與資源需求,計算機系統在運行過程中可能出現資源不足的情況,運行資源不足表現為性能低和死鎖兩種情況。
解決辦法為進程掛起:剝奪某些進程的內存及其他資源,調入OS管理的對換區,不參加進程調度,待適當時候再調入內存、恢復資源、參與運行
一般選擇等待態進程進入掛起等待態,也可選擇就緒態進程進入掛起就緒態,運行態進程還可以掛起自己進入掛起就緒態
等待事件結束后,掛起等待態進入掛起就緒態,一般選擇掛起就緒態進程予以恢復
⭐️掛起態與等待態有着本質區別,等待態占有已申請到的資源處於等待,掛起態沒有任何資源
進程映像(Process Image)是某一時刻進程的內容及其執行狀態集合,是內存級的物理實體,又稱為進程的內存映像,包括了:
(1)進程控制塊PCB(Process Control Block)是OS用於記錄和刻畫進程狀態及環境信息的數據結構。
借助PCB,OS可以全面管理進程的物理實體,刻畫進程的執行現狀,控制進程的執行
-
標識信息:用於存放唯一標識該進程的信息
系統分配的標識號、系統分配的進程組標識號、用戶定義的進程名、用戶定義的進程組名
-
現場信息:用於存放該進程運行時的處理器現場信息,:
用戶可見寄存器內容:數據寄存器、地址寄存器
控制與狀態寄存器內容:PC、IR、PSW
棧指針內容:核心棧與用戶棧指針
-
控制信息:用於存放與管理、調度進程相關的信息
調度相關信息:狀態、等待事件/原因、優先級
進程組成信息:代碼/數據地址、外存映像地址
進程隊列指引元:進程隊列指針、父子兄弟進程指針
進程通信相關信息:消息隊列、信號量、鎖
進程處理器使用信息:占用的處理器、時間片、處理器使用時間/已執行總時間、記賬信息
進程特權信息:如內存訪問權限、處理器特權
進程資源清單信息:如正占有的資源、已使用的資源
(2)進程程序塊: 進程執行的程序空間
(3)進程數據塊: 進程處理的數據空間,包括數據、處理函數的用戶棧和可修改的程序
(4)進程核心棧: 進程在內核模式下運行時使用的堆棧,中斷或系統過程使用
除了進程映像,進程的執行還需要環境支持,包括CPU現場和Cache中的執行信息, OS中的進程物理實體(代碼和數據等)和支持進程運行的環境合成進程上下文,用於刻畫進程的執行情況,進程在當前上下文中運行。
進程上下文包括:
(1)用戶級上下文:用戶程序塊/用戶數據區/用戶堆棧/用戶共享內存組成的用戶空間信息
(2)寄存器上下文:即進程的現場信息,包括PSW/棧指針/通用寄存器。
(3)系統級上下文:由進程控制塊(進程的狀態)、內存管理信息(進程頁表或段表)和系統核心棧(進程內核態運行時的工作區)等操作系統管理進程需要的信息
用戶級上下文地址空間和系統級上下文地址空間一起構成了一個進程的整個存儲器映像。
關鍵的進程管理軟件包括:
(1)系統調用/中斷/異常處理程序
(2)隊列管理模塊
(3)進程控制程序
(4)進程調度程序(獨立進程居多)
(5)進程通信程序(多個程序包)
(6)終端登錄與作業控制程序、性能監控程序、審計程序等外圍程序
把處於同一狀態的所有進程的PCB鏈接在一起的數據結構稱為進程隊列,有兩種常用的隊列組織方式:
(1)索引方式:系統建立若干索引表,各索引表在內存中的起始地址放在內核專用指針單元。
(2)鏈接方式:隊列中的進程可以通過PCB中的隊列指引元采用單向鏈接或雙向鏈接,系統為每個隊列設置隊列標志以標志和識別隊列。
進程實現的隊列模型如圖所示:
隊列管理模塊是操作系統實現進程管理的核心模塊。進程與資源調度圍繞進程隊列展開。
操作系統建立多個進程隊列,如只有一個進程的運行隊列、按照優先級或FCFS排列的就緒隊列、等待I/O操作完成的隊列、等待信號量的隊列等。按需組織為先進先出隊列與優先隊列
當發生某個事件使進程狀態發生轉換時,此進程退出所在隊列進入另一個隊列。
進程的控制與管理:
- 進程創建:進程列表加一項,申請PCB並初始化,分配唯一進程標識符,建立映像,分配資源,移入就緒隊列
- 進程撤銷:從隊列中移除,歸還資源,撤銷標識符,回收PCB,移除進程表項(先要撤銷子進程)
- 進程阻塞:保存現場信息,修改PCB,移入等待隊列,轉向進程調度程序調度其他進程執行
- 進程喚醒:等待隊列中移出,修改PCB,移入就緒隊列(該進程優先級高於運行進程,則重新設置調度標志)
- 進程掛起:修改狀態並出入相關隊列,收回內存等資源送至對換區
- 進程激活:分配內存,修改狀態並出入相關隊列
- 其他:如修改進程特權
進程控制過程中涉及對OS核心數據結構(進程表/PCB池/隊列/資源表)的修改,為防止與時間有關的錯誤,應使用原語(由若干條指令構成的完成某種特定功能的程序,執行上具有不可分割性,執行可以通過關中斷實現)。進程控制使用的原語稱為進程控制原語。
PS:另一類常用原語是進程通信原語。
Linux將用戶空間對應的進程虛擬空間組織成若干區域(area)的集合,這些區域是指在虛擬存儲空間中的連續片,而且是已分配頁。
例如:只讀代碼區、可讀寫數據區、已分配堆區、已分配棧區、共享映射區。每個區再被分配成等大頁面。
每個進程主要通過一個稱為進程描述符(process descriptor)的結構來描述,其結構類型定義為task_struct,包含了一個進程的所有信息:標識進程的PID、指向用戶棧的指針、可執行目標文件的文件名、程序計數值PC等。
所有進程通過一個雙向循環鏈表實現的任務列表(task list)來描述,任務列表中每個元素是一個進程描述符。
如圖,task結構中有一個指針指向mm結構,mm結構描述對應進程虛擬空間的當前狀態,其中有一個字段pgd,對應進程第一級頁表(頁目錄表)的首地址,當處理器運行對應進程時,內核會將其送到CR3控制寄存器;以及一個字段mmap,指向一個由vm_area結構組成的鏈表表頭。
每個vm_area結構了對應進程虛擬空間中的一個區域。包括指向區域開始位置和結束位置的vm_start和vm_end,描述區域包含的所有頁面的訪問權限的vm_prot,描述區域包含的頁面是否和其它進程共享的vm_flags。以及指向下一個鏈表結點的vm_next。
例如,read不存在的區域,就會引起段故障;read可讀寫數據區一切正常;write只讀代碼區就會發生段故障的保護異常。
總結,Linux是以鏈表方式管理用戶空間中的區域area,內核不需要記錄那些不存在的頁面。通過task結構、task結構指向的mm結構、mm結構指向的其它結構來記錄進程標識信息、進程現場信息、進程控制信息。
進程切換指從正在運行的進程中收回處理器,讓待運行進程來占有處理器運行,實質上就是被中斷運行進程與待運行進程的上下文切換,處理過程是:
-
保存被中斷進程的上下文
-
轉向進程調度
-
恢復待運行進程的上下文
其一定發生在中斷/異常/系統調用處理過程中,常見的情況是:
-
阻塞式系統調用、虛擬地址異常導致被中斷進程進入等待態
-
時間片中斷、I/O中斷后發現更高優先級進程導致被中斷進程轉入就緒態
-
終止用系統調用、不能繼續執行的異常導致被中斷進程進入終止態
進程切換必須在操作系統內核模式下完成,這就需要模式切換(處理器狀態切換),模式切換包括:
-
(1)用戶模式到內核模式,由中斷/異常/系統調用中斷用戶進程執行而觸發
由中斷裝置完成正向模式切換,包括(1)處理器模式轉為內核模式;
(2)保存當前進程的PC/PSW值到核心棧;
(3)轉向中斷/異常/系統調用處理程序
-
內核模式到用戶模式,OS執行中斷返回指令將控制權交還用戶進程而觸發
由中斷返回指令完成逆向模式轉換,包括(1)從待運行進程核心棧中彈出PSW/PC值;
(2)處理器模式轉為用戶模式
綜上,完整的進程切換過程為
-
(中斷/異常等觸發)正向模式切換並壓入PSW/PC
-
保存被中斷進程的現場信息
-
處理具體中斷/異常
-
把被中斷進程的系統堆棧指針SP值保存到PCB
-
調整被中斷進程的PCB信息,如進程狀態
-
把被中斷進程的PCB加入相關隊列
-
選擇下一個占用CPU運行的進程
-
修改被選中進程的PCB信息,如進程狀態
-
設置被選中進程的地址空間,恢復存儲管理信息
-
恢復被選中進程的SP值到處理器寄存器SP
-
恢復被選中進程的現場信息進入處理器
-
中斷返回指令觸發逆向模式轉換並彈出PSW/P
一些中斷/異常不會引起進程狀態轉換,不會引起進程切換,只是在處理完成后把控制權交回給被中斷進程,處理流程為
-
中斷/異常觸發正向模式切換壓入PSW/PC
-
保存被中斷進程的現場信息
-
處理中斷/異常
-
恢復被中斷進程的現場信息
-
中斷返回指令觸發逆向模式轉換彈出PSW/PC