第二章 進程管理
2.1 前驅圖和程序執行
前驅圖是一個有向無循環圖,記為DAG,可用於描述程序/進程之間執行的前后關系。

程序的順序執行:在計算機系統中只有一個程序在運行,這個程序獨占系統中所有資源,其執行不受外界影響,一道程序執行完后另一道才開始。
特點:順序性、封閉性、可再現性(程序的結果與運行時間無關,只與初始條件有關)
程序的並發執行:若干程序同時在系統中執行,這些程序的執行的執行在時間上是重疊的,一個程序的執行尚未結束,另一個程序的執行已經開始。
特點:間斷性、失去程序的封閉性(多個程序共享系統中的資源,資源狀態將由多個程序來改變)、不可再現性
進程
進程的定義:進程就是程序關於某個數據集合的一次執行過程。能夠更加真實的描述並發
進程實體:程序段、相關的數據段、進程控制塊PCB。
進程是指進程實體的運行過程,是系統進行資源分配和調度的一個獨立單位。
進程=程序+數據+PCB
如果進程中有n個進程,運行進程最多1個,最少0個;就緒進程最多n-1個,最少0個;等待進程最多n個,最少0個
進程的特征:1.結構特征(由程序段、數據段、進程控制塊三部分組成);
2.動態性(進程是程序的執行);
3.並發性(多個進程可同存於內存中,能在一段時間內同時運行);
4.獨立性(獨立運行的基本單位,獨立獲得資源和調度的基本單位);
5.異步性(各進程按各自獨立的不可預知的速度向前推進);
進程的三種基本狀態
就緒狀態:進程已經獲得除CPU外的所有資源,得到CPU,就立即可以運行
就緒隊列:處於就緒狀態進程所在隊列
運行狀態:正在運行的進程所處的狀態
阻塞/等待狀態:進程正等待某一事件發生(如等待輸入輸出完成),這時即使給它CPU也無法運行
阻塞隊列:系統根據阻塞原因設置多個隊列來管理處於阻塞狀態的進程
五狀態:創建狀態(許可)、終止狀態(釋放)
七狀態:掛起狀態(暫時被淘汰出內存的進程)(引入原因:終端用戶請求、父進程請求、負荷調節需要、操作系統需要)
進程控制塊(PCB):為了描述和控制進程運行系統為每個進程定義的數據結構,記錄了OS所需的、用於描述進程當前情況以及控制進程運行的全部信息。
PCB的內容:
進程描述信息:描述標識符(唯一,通常一個整數);進程名(通常基於可執行文件名);用戶標識符(進程的家族關系);
進程控制信息:當前狀態,優先級,代碼執行入口地址,程序的外存地址,運行統計信息,進程間同步和通信,阻塞原因,進程的隊列指針,進程的消息隊列指針
所擁有的資源和使用情況:已分配到該進程的資源清單,打開文件列表
CPU現場保護信息:通用寄存器、指令寄存器、棧指針(存放過程和系統調用的參數和調用地址)
PCB的作用:
將一個不能獨立運行的程序變成一個可以獨立運行的基本單位,一個能與其他進程並發執行的進程。
OS利用PCB來對並發執行的過程進行控制和管理,PCB是OS感知進程存在的唯一標志
進程與PCB是一一對應的;PCB應常駐內存。
PCB表組織方式
系統把所有進程的PCB組織在一起,並把它們放在內存的固定區域,就構成了PCB表。
PCB表的大小決定了系統中最多可同時存在的進程個數,稱為系統的並發度
相同狀態的進程組成一個鏈表,不同狀態對應不同的鏈表
對具有相同狀態的進程,分別設置各自的PCB索引表,存放這些進程PCB在PCB表中的地址。
2.2 進程控制
● 進程控制是對系統中的所有進程實施管理
創建一個新進程、終止一個已完成的進程、終止一個因出現某事件而無法運行下去的進程、負責進程運行中狀態的轉換
● 進程控制一般由OS內核的原語來實現
原語:一種特殊的功能調用,它可以完成一個特定的功能 (特點:不可打斷,常駐內存,運行在管態)
常見原語:創建原語Create 終止原語Destory 阻塞原語Block 喚醒原語Wakeup 掛起原語Suspend 激活原語Active
Q:普通的程序可以實現進程控制嗎?
A:不能,用戶無法訪問PCB表;不是原語操作會被打斷,被中斷后,程序運行狀態不穩定
進程創建
1.申請空白PCB
2.為新進程分配資源 如內存
3.初始化進程控制塊
4.將新進程插入就緒隊列
Q:什么事件可以引起創建進程?
A:作業調度,用戶登錄,提供服務(打印等),應用請求(創建多個子進程,並發執行,提高速度)
進程終止
1.根據被終止進程的標識符,從PCB表中檢索出該進程的PCB
2.若被終止進程處於執行狀態,應立即終止執行,並置調度標志為真 (CPU空閑)
3.結束該進程所有子孫進程的執行,以防成不可控進程(類似刪除文件夾)
4.將進程所擁有的資源交給父進程或系統進程
5.釋放PCB
進程終止原因:正常退出、異常退出、外界干預
進程的阻塞與喚醒
阻塞:當一個進程所期待的事件還未出現時,自己調用阻塞原語將自己阻塞 (主動行為)
引起原因:請求系統服務(請求打印機)、啟動某種操作(輸入未完成時請求)、新數據尚未到達、無新工作可做
喚醒:當被阻塞進程所期待的事件出現時,則由有關進程調用喚醒原語將該進程喚醒
(處於阻塞狀態的進程不可能自己喚醒自己,必須由合作進程用喚醒原語喚醒它)
進程的掛起與激活:系統利用對應原語進行
2.3 線程
線程引入的原因:應用的需要、開銷/性能的考慮
線程的開銷較小:(創建一個新線程花費時間少,兩個線程切換花費的時間少,線程之間相互通信不用調用內核)
線程:進程中的一個運行實體,是CPU的調度單位,有時將線程稱為輕量級進程
線程的內容:程序計數器、寄存器組(不運行時需要保存上下文)、堆棧、子線程、狀態(可轉換)
線程共享所在進程的地址空間和其它資源,可以創建、撤銷另一個線程
線程的分類 用戶級線程、內核級線程、混合級線程
2.4 進程同步
並發是所有問題產生的基礎,並發是操作系統設計的基礎
進程互斥
由於各進程要求使用共享資源(變量、文件等),這些資源需要排他性使用。各進程之間競爭使用這些資源,這一關系稱為進程互斥。
臨界資源(互斥資源、互斥變量):系統中某些資源一次只允許一個進程使用
臨界區(互斥區):各個進程中對某個臨界資源(共享變量)實施操作的程序片段
使用原則:空閑讓進、忙則等待、有限等待、讓權等待
進程同步
指系統中多個進程中發生的事件存在某種時序關系,需要共同合作完成一項任務(一個進程需要另一個進程喚醒)
生產者、消費者問題 ★★★
問題描述:1.一個或多個生產者 生產某種類型的數據放置在緩沖區中
2.有消費者從緩沖區中取數據,每次取一項
3.只能有一個生產者或消費者對緩沖區進行操作
要解決的問題:
1.當緩沖區已滿時,生產者不會繼續向其中添加數據
2.當緩沖區為空時,消費者不會從中移除數據
參考代碼:
生產者() { i=0; while(1) { //生產產品; P(mutex); //往buffer[i]放產品 i=(i+1)%n; V(mutex); V(full); } } 消費者() { while (1) { P(full); P(mutex); //從Buffer[j]取產品 j=(j+1)%n; V(mutex); //消費產品 } }
因有M個生產者,N個消費者,會對有界緩沖區進行操作,必須互斥使用,需設置一個互斥信號量mutex,初值為1.
<可設置兩個同步(資源)信號量:分別代表空緩沖區數目(初值為緩沖區大小)和已用緩沖區數目(初值為0)>
2.5 信號量機制
信號量就是OS提供管理共有資源的有效手段;信號量代表可用資源的實體的數量
整型信號量 未遵循“讓權等待”導致“忙等”。
定義為一個整型量,除初始化外,由兩個標准原子操作Wait(S)(P操作)和singal(S)(V操作)來訪問
P,V操作是原子操作,不可中斷!
記錄型信號量
記錄型信號量機制采取“讓權等待”策略,避免了整型信號量出現的“忙等”現象。
實現:一個用於代表資源數目的整型變量value,一個用於鏈接所有阻塞進程的進程鏈表queue
P操作:申請資源,減量操作 s.value=s.value-1;當s.value<0時,表示資源分配完,進行自我阻塞
V操作:釋放資源,增量操作 s.value=s.value+1;當s.value<=0時,喚醒s.queue中的等待進程
value>0:代表可用資源數量 value<0:代表由於申請資源而阻塞的進程
AND型信號量
將進程在整個運行過程中所需要的資源一次性全部分配給進程,待進程使用完后再一起釋放,只要尚有一個資源未分配給進程,其它所有可能為之分配的資源也不分配給它。(實現:在wait 操作中,增加一個“AND”條件)
信號量集
<一次需要N個某類臨界資源時,就要進行N次P操作--低效又可能死鎖>
同時需要多個資源、每種占用的數量不同、且可分配的資源還存在一個臨界值時的信號量處理,在一次原語操作中完成所有的資源申請。
一般“信號量集”未必成對使用 如:一起申請,但不一起釋放
swait(s,d,d)表示每次申請d個資源,少於d個時不分配
信號量的應用
利用信號量實現進程互斥
只需為臨界資源設置一互斥信號量mutex,設其初始值為1;將各進程臨界區置於wait(mutex)和singal(mutex)之間即可;
1 semaphore mutex=1; 2 P1() 3 { 4 while(1) 5 { 6 wait(mutex); 7 //臨界區 8 signal(mutex); 9 //剩余區 10 } 11 }
用信號量機制解決進程同步問題 ★★★
1.定義信號量(資源信號量、互斥信號量)
2.給信號量賦初值
3.對信號量進行P,V操作
① 互斥信號量的P,V操作總是成對出現
② 資源信號量的P,V操作可能出現在合作進程中。
2.6 管程機制
信號量機制的缺點:進程自備的同步操作,P(S)和V(S)操作大量分散在各個進程中,不易管理,易發生死鎖。
解決方法:引入管程:為每個可共享資源設立一個專門的管程,統一管理各進程對該資源的訪問(封裝同步操作,隱蔽細節,簡化調用)
管程:由關於共享資源的數據結構及在其上操作的一組過程組成。進程只能通過管程中的過程來間接地訪問管程中的數據
管程解決的問題:互斥、同步
管程是互斥進入的,設置條件變量及等待/喚醒操作已解決同步問題(可讓一個進程或管程在條件變量上等待(此時,應釋放管程的使用權),也可以通過發送信號將等待在條件變量上的進程或線程喚醒)
管程通常用於管理資源,管程中有進程等待隊列和相應的等待和喚醒操作
2.7 進程通信
引入原因:信號量及管程的不足:不適用多處理器的情況(解決進程間同步問題、通信問題)
基本通信方式:消息傳遞、共享內存、管道