文章目錄
第二章 併發與進程
2.1 進程的概念
★ 進程
一個正在執行的程序、正在運行的程序的一個實例、由處理器執行的一個實體
進程 = 進程控制塊(PCB) + 程序段 + 數據段 + 棧
- 引入目的:
使多道程序能夠正確地併發執行 - 進程的兩個基本屬性:
– 擁有資源的獨立單位:一個進程包括一個保存進程映像的虛地址空間,擁有對資源的控制或所有權。
– 調度/執行的基本單位:一個具有狀態和優先級,可被被操作系統調度並分派的實體。
★ 基本特徵
- 動態性:(本質特性) 一個正在計算機上執行的程序實例,存在生命週期
- 併發性:(重要特性) 任何進程都可以同其他進程一起向前推進
- 獨立性:各進程的地址空間相互獨立,除非採用進程間通信手段
- 異步性:按各自獨立的、不可預知的速度向前推進
- 結構性
★ 進程的狀態轉換
- 就緒狀態:進程在內存,已分配到除CPU之外的所有必要資源,準備執行
- 執行狀態:進程已獲得CPU,其程序正在執行。
- 阻塞狀態:正在執行的進程由於需要等待某個事件發生而暫時無法繼續執行。
- 新建狀態:OS已完成爲創建一個進程所必要的工作,但進程自身還未進入主存。
- 終止狀態:進程完成或發生錯誤,其表格和其他信息暫時保留。
- 掛起狀態:進程交換到外存,不再參與CPU的競爭。<—> 對換技術
- 就緒/掛起:進程在外存,只要調入內存並獲得CPU即可執行
- 阻塞/掛起:進程在外存,等待事件
2.2 操作系統爲控制程序所建立的數據結構
內核的概念:一些與硬件緊密相關、基本的、公共的、運行頻率較高的模塊,以及關鍵性數據結構等常駐內存,便於提高操作系統運行效能的這部分軟件,稱爲操作系統的內核。
★ 操作系統內核的功能
- 資源管理功能:進程管理、存儲管理、I/O設備管理
- 支撐功能:中斷處理、時鐘管理、原語操作、統計監測功能
★ 操作系統控制結構
操作系統構造並維護它所管理的每個實體的信息表,一般有4種不同類型的表:內存、I/O、文件和進程。
★ 進程控制塊
進程控制塊的作用: 進程存在的唯一標誌;PCB常駐內存。
進程控制塊中的信息:
- 進程標示符:唯一地標識一個進程。內部、父、用戶標識符
- 處理機狀態信息:通用寄存器、指令計數器、程序狀態字、用戶棧指針
- 進程控制信息:進程狀態、進程優先級、進程調度所需的其他信息、事件
- 其他信息:程序和數據的地址、進程同步和通信機制、資源清單、鏈接指針
進程控制塊的組織方式:
- 索引方式、
- 鏈接方式(單一隊列、多級隊列)
2.3 操作系統對進程的控制
2.3.1 進程的創建
引起創建進程的事件
- 用戶登錄、爲新的作業創建進程、操作系統因爲提供一項服務而創建、由現有的進程派生
創建進程的步驟:
- 給新進程分配一個唯一的進程標識符
- 爲進程分配空間、初始化進程控制塊
- 建立鏈接,將之插入就緒或就緒/掛起鏈表
- 建立或擴充其它數據結構
2.3.2 進程的撤銷
引起進程終止的事件
- 正常結束、異常結束(越界錯誤、保護錯、非法指令、特權指令錯、運行超時、等待超時、算術運算錯、I/O故障)、外界干預(程序員kill進程、父進程終止、父進程請求)
進程終止的步驟
- 根據被終止進程的標識符找到其PCB,讀出該進程的狀態
- 若該進程爲執行狀態,則終止其執行,調度下一個就緒進程執行
- 若該進程還有子孫進程,還應將其所有子孫進程予以終止
- 將該進程所擁有的全部資源,或者歸還給其父進程,或者歸還給系統
- 將被終止進程的PCB從所在隊列中移出
2.3.3 進程的阻塞
引起阻塞的事件
- 請求系統服務而得不到滿足、啓動某操作而需同步、新數據尚未到達、無新工作
進程阻塞的步驟
- 進程通過調用阻塞原語block( )把自己阻塞
- 將PCB中的狀態由“執行”改爲“阻塞”,並將PCB插入阻塞隊列
- 調度程序將處理機分配給另一就緒進程,並進行切換
2.3.4 進程的喚醒
- 由有關進程調用喚醒原語wakeup( )將等待該事件的進程喚醒
- 被阻塞的進程從等待該事件的阻塞隊列中移出
- 將其PCB中的現行狀態由阻塞改爲就緒
- 將該PCB插入到就緒隊列中
2.3.5 進程的掛起
引起掛起suspend( )的事件
- 內存資源緊張、進程全部阻塞,CPU空閒
程序掛起的步驟: - 檢查被掛起進程的狀態,若處於就緒狀態,便將其改爲就緒/掛起
- 對於處於阻塞狀態的進程,則將之改爲阻塞/掛起
- 將進程移出內存
2.3.6 進程的激活
- 將進程從外存處於掛起狀態的進程調入內存,激活原語active()
- 檢查該進程的現行狀態: 若是就緒/掛起,便將之改爲就緒;若爲阻塞/掛起,便將之改爲阻塞
2.3.7 進程切換
概念:調度另一個就緒進程佔用處理器執行
何時發生:時鐘中斷、I/O中斷、內存失效、陷阱、系統調用
進程切換的步驟:
- 保存處理器上下文環境,包括程序計數器和其它寄存器
- 更新當前處於運行狀態進程的進程控制塊
- 將進程的進程控制塊移至相應隊列(就緒、阻塞等)
- 選擇另一進程執行
- 更新其進程控制塊信息
- 恢復被選擇進程的上下文環境
★ UNIX進程控制
fork():創建一個新進程。
調用格式: pid = fork()
在調用fork()之後,父進程和子進程均在下一條語句上繼續運行。在子進程中返回時,pid爲0;在父進程中返回時,pid爲所創建的子進程的標識。
2.4 線程
2.4.1 線程的概念
概念:線程又叫輕量級進程,進程的一個實體,是系統獨立調度和分派的基本單位。
優勢:增加系統的併發性,減少併發執行時的時空開銷。
屬性
- 除了一點必不可少的資源(如TCB、程序計數器、寄存器和堆棧)外,線程基本
上不擁有系統的資源 - 獨立調度和分派的基本單位
- 同一個進程中的多個線程以及不同進程中的多個線程均可併發執行
- 同一個進程中的各線程可以共享該進程中所擁有的全部資源,如進程的地址空
間、已打開的文件、定時器和信號量等
2.4.2 進程與線程的關係
2.4.3 多線程併發
線程的基本狀態:
- 就緒狀態、執行狀態、阻塞狀態
線程的基本操作:
- 派生:線程可以由進程或線程所派生
- 阻塞:等待某事件,並釋放處理機
- 解除阻塞:等待的事件發生,狀態變成就緒,插入就緒隊列,等待調度執行。
- 結束:執行完畢,釋放其私有資源
2.4.4 線程的類型
- 用戶級線程:操作由應用程序完成;操作系統不知道線程存在,仍以進程爲調度單位。
- 內核級線程:操作由系統內核完成,以線程爲調度單位。
- 混合線程:操作由應用程序完成,多個用戶級線程被影射到一個或較少的某些內核級線程
2.5 進程調度
2.5.1 調度的目標和原則
目標:防止飢餓、提高處理器的利用率、提高系統吞吐量、減少響應時間
原則:用戶的需求(響應時間快、平均週轉時間短、滿足截止時間)、系統的需求(吞吐量大、CPU利用率高、各類資源的平衡使用、公平性、優先權)
2.5.2 調度的類型
長程調度(高級調度、作業調度):
- 決定外存上處於後備隊列中的哪個作業調入內存
- 爲它們創建進程、分配必要的資源
- 將新創建的進程排在就緒隊列(就緒/掛起)上,等待短程(中程)調度。
中程調度(中級調度)
- 對換功能的一部份,用以提高內存的利用率和系統的吞吐量。
- 內存緊張時,選擇一個進程換出到外存(換出)。
- 內存充裕時,從外存選擇一個掛起狀態的進程調度到內存(換入)。
- 只有支持進程掛起的操作系統才具有中程調度功能
短程調度(進程調度、低級調度)
- 決定就緒隊列中的哪個進程應獲得處理器
- 運行頻率最高
- 現代操作系統幾乎都具有短程調度功能
2.5.3 一些相關的基本概念
- 響應時間:從用戶通過鍵盤提交一個請求開始,直至系統首次產生響應爲止的時間。
響應時間 = 輸入傳送時間 + 處理時間 +響應傳送時間 - 週轉時間:從作業被提交給系統開始,到作業完成爲止的時間。
= 駐外存等待調度時間 + N *(駐內存等待調度時間+執行時間+阻塞時間) - 帶權週轉時間:作業的週轉時間與系統爲它提供服務的時間之比。
- 截止時間:某任務必須開始執行的最遲時間,或必須完成的最遲時間。一般用於實時系統。
- 系統吞吐量:在單位時間內系統所完成的作業數。
2.5.4 調度的分類
按是否剝奪當前進程來分:非剝奪方式、剝奪方式
按被調度進程的狀態來分:長程調度、中程調度、短程調度
2.5.5 常見的調度算法
2.6 實時系統與實時任務調度
實時系統的基本要求:
可確定性、可響應性、用戶控制、可靠性、失效弱化
實時任務的分類
按截止時間分:硬實時任務、軟實時任務
按週期性分:週期性任務、非週期性任務
實時調度的目標
使硬實時任務在其規定的截止時間內完成(或開始),同時儘可能使軟實時任務也能在規定的截止時間內完成(或開始)。
★ 常見的實時調度算法
(1) 基於時間片輪轉的調度 秒級,用於分時、一般實時處理系統
(2) 基於優先級的非搶佔調度 百毫秒~數秒級,用於多道批處理系統
(3) 基於優先級的搶佔點搶佔調度 幾毫秒~幾十毫秒,一般實時系統
(4) 立即搶佔式調度 毫秒級,苛刻的實時系統
(x) 限期(deadline)調度: 最早截止時間優先調度算法(EDF)
最低鬆弛度優先調度算法(LLF)
速度單調調度算法(RMS)
鬆弛度=完成截止時間-剩餘執行時間-當前時間
2.7 併發控制
★ 相關概念
臨界資源:一次僅允許一個進程訪問的資源爲臨界資源
臨界區:把在每個進程中訪問臨界資源的那段代碼稱爲臨界區。臨界區是一段代碼,在這段代碼中進程將訪問臨界資源,當另外一個進程已經在這段代碼中運行時,這個進程就不能在這段代碼中執行。
死鎖:兩個或兩個以上的進程相互等待導致都不能執行
互斥:當一個進程在臨界區訪問臨界資源時,其他進程不能進入該臨界區訪問共享資源
競爭:多個進程讀寫一個共享數據時依賴它們執行的相對時間
飢餓:一個進程已經完全具備了執行的條件,但是得不到CPU資源
★ 進程間的制約關係
間接制約:資源共享–>互斥
直接制約:進程合作–>同步
★ 臨界區使用原則(互斥條件)
- 空閒讓進:如臨界區空閒,則有進程申請就立即進入。
- 忙則等待:每次只允許一個進程處於臨界區。
- 有限等待:保證進程在有限時間內能進入臨界區。
- 讓權等待:進程在臨界區不能長時間阻塞等待某事件。
2.8 互斥與同步的解決策略
★ 軟件方法
在進入區設置和檢查一些標誌來標明是否有進程在臨界區。若已有進程在臨界區,則在進入區通過循環檢查進行等待,進程離開臨界區後則在退出區修改標誌。
始終存在忙等問題。
通常能實現兩個進程的互斥,很難控制多個進程的互斥。
★ 硬件方法
屏蔽中斷:避免進程切換,實現互斥訪問。
專用機器指令:設計專門的機器指令用於保證動作的原子性,如Test&Set、Exchange。
硬件方法支持多處理機和多臨界區,但存在忙等、飢餓和死鎖的現象。
★ 信號量方法
信號量實現進程互斥的基本原理
- 兩個或多個進程可以通過傳遞信號進行合作,可以迫使進程在某個位置暫時停止
執行(阻塞等待),直到它收到一個可以“向前推進”的信號(被喚醒)。 - 信號量s一個域爲整型,另一個域爲隊列(等待該信號量的阻塞進程們)
信號量的定義
信號量的兩個原子操作
信號量的類型
- 互斥信號量:用於申請或釋放資源的使用權,初始值爲1。範圍: [ -(n-1), 1 ] 。
- 資源信號量:用於申請或歸還資源,表示某資源的可用數目。範圍: [ m-n, m]
n個進程共享臨界資源: -(n-1)≤s.count ≤1
★ 管程
管程是一個程序設計語言結構,採用了集中式的進程同步方法,提供了與信號量同樣的功能,但更易於控制。一個管程定義了一個數據結構和能爲併發進程所執行(在該數據結構上)的一組操作,這組操作能同步進程和改變管程中的數據。(C. A. R. Hoare & Per Brinch Hansen)
管程是由一個或多個過程、一個初始化序列和局部數據組成的軟件模塊。主要特點:
- 局部數據變量只能被管程的過程訪問,任何外部過程都不能訪問。
- 一個進程通過調用管程的一個過程進入管程。
- 在任何時候,只能有一個進程正在管程執行,調用管程的任何其它進程都被阻塞,以等待管程可用。
2.9 生產者/消費者問題
- 應先申請資源信號量,再申請互斥信號量,順序不能顛倒。
- 同一進程中的多對wait和signal語句可以嵌套,也可以交叉。
- 對於同一個信號量的wait與signal操作,既可以出現在同一個進程中,也可以出現在不同進程中。
- 對任何信號量的wait與signal操作必須配對。
- 在進入臨界區前必須先執行wait操作,退出臨界區後必須執行signal操作。對於同一信號量而言,既有可能先執行wait操作,也有可能先執行signal操作。
★ 1個生產者、2個消費者被連接到大小爲N的緩衝區上,2個消費者分別消費不同資源
- 盤子是一互斥資源,故設置互斥信號量mutex(1)
- 爸爸、兒子因爲桔子的放入與取出而同步,設置資源信號量orange(0)
- 爸爸、女兒因爲蘋果的放入與取出而同步,設置資源信號量apple(0)
- 爸爸、兒子、女兒因爲共享盤子,設置資源信號量empty(N)
★ 2個生產者、2個消費者被連接到大小爲1的緩衝區上,2個生產者分別生產不同的資源,2個消費者也分別消費不同的資源
- 盤子是一互斥資源,故設置互斥信號量plate(1)
- 爸爸、女兒因爲蘋果的放入與取出而同步,設置資源信號量apple(0)
- 媽媽、兒子因爲桔子的放入與取出而同步,設置資源信號量orange(0)
★ 2個生產者、1個消費者被連接到大小爲2的緩衝區上,2個生產者分別生產不同的資源,當兩種資源同時存在時消費者才能進行消費
- 盤子是一互斥資源,故設置互斥信號量mutex(1)
- 盤子中是否可以放入蘋果,設置信號量empty_apple(1)
- 盤子中是否可以取出蘋果,設置信號量apple(0)
- 盤子中是否可以放入桔子,設置信號量empty_orange(1)
- 盤子中是否可以取出桔子,設置信號量orange(0)
★ 1個生產者、2個消費者被連接到大小爲1的緩衝區上,每個數據被消費兩次才結束生命週期,消費者可以同時消費同一數據
- 爸爸是否欣賞過,設置資源信號量empty_dad(1)
- 爸爸是否可以欣賞,設置資源信號量full_dad(0)
- 媽媽是否欣賞過,設置資源信號量empty_mom(1)
- 媽媽是否可以欣賞,設置資源信號量full_mom(0)
2.10 讀者、寫者問題
允許多個讀者進程可以同時讀數據;
不允許多個寫者進程同時寫數據,即只能互斥寫數據;
若有寫者進程正在寫數據,則不允許讀者進程讀數據——互斥讀寫。
★ 讀者優先
一旦有讀者正在讀數據,則允許隨後的讀者進入讀數據。只有當全部讀者退出,才允許寫者進入寫數據。導致寫者飢餓
- wsem:互斥信號量,用於Writers互斥Writers和Readers,以及第一個Reader互斥Writers。(1)
- readcount:統計同時讀數據的Readers個數(int型/0)
- mutex:對變量readcount互斥算術操作(1)
★ 公平優先
讀者、寫者的執行順序與到達順序嚴格一致。
- wsem:互斥信號量,用於…
- readcount:統計同時讀數據的Readers個數(int型/0)
- mrc:對變量readcount互斥算術操作(1)
- wrsem:互斥信號量,確定Writer 、Reader請求順序(1)
★ 寫者優先
只要有一個寫者申請寫數據,則不再允許新的讀者進入讀數據。解決了寫者飢餓問題,但降低了併發程度,系統的併發性能較差。
- rsem:互斥信號量,當至少有一個寫者申請寫數據時互斥新的讀者進入讀數據(1)
- wsem:互斥信號量,用於…(1)
- readcount:統計同時讀數據的Readers個數(int/0)
- writecount:用於控制rsem信號量(int/0)
- mrc:對變量readcount互斥算術操作(1)
- mwc:對變量writecount互斥算術操作(1)
2.11 進程間的通信
進程通信:進程之間的信息交換
★ 共享存儲區
★ 消息傳遞
兩條通信原語:Send(destination,message)、Receive(source,message)
三種同步方式:
- 阻塞發送,阻塞接收;
- 不阻塞發送,阻塞接收;
- 不阻塞發送,不阻塞接收
郵箱:不不限制進程數,允許多個發送進程向郵箱發送消息,同時,也允許多個接收進程從郵箱接收消息
利用消息傳遞實現互斥
- 共享一個郵箱,初態僅包含一條空消息;
- 採用“不阻塞發送,阻塞接收”方式傳遞消息;
- 若郵箱中存在一條消息,則允許一個進程進入臨界區。
- 若郵箱爲空,表明有一個進程位於臨界區,其它試圖進入臨界區的進程必須阻塞。
- 只要保證郵箱中最多隻有一條消息,就能保證只允許一個進程進入臨界區,從而實現進程互斥使用臨界資源。
利用消息傳遞解決生產者/消費者問題
- 使用capacity條消息,其作用類似於緩衝區的大小;
- capacity條消息的初始狀態爲“空”消息,類似於緩衝區的初始狀態爲空(未填充生產數據);
- 生產者生產一條數據後,取一條“空”消息,併發送回一條填充了數據的消息;
- 消費者消費一條數據後,取一條填充了數據的消息,併發送回一條“空”消息;
- 若生產者速度快於消費者消速度,則因無“空”消息可用而阻塞;
- 若消費者速度快於生產者消速度,則因無填充了數據的消息可用而阻塞。
2.12 進程死鎖
★ 死鎖的概念
多個進程因爲競爭資源或執行時推進的順序不當,或相互通信出現永久阻塞現象,如果沒有外力作用,這種現象將永遠保持下去。
★ 產生死鎖的原因
- 資源不足導致的資源競爭
- 併發執行的順序不當
★ 產生死鎖的充分必要條件
- 互斥、佔有且等待、非剝奪條件是死鎖產生的必要條件,但不是充分條件。
- 循環等待條件實際上是互斥、佔有且等待、非剝奪條件的可能導致的結果。
- 只要系統出現循環等待,則一定出現死鎖。
- 互斥、佔有且等待、非剝奪條件、循環等待條件構成了死鎖產生的充分必要條件。
★ 解決死鎖的方法
- 預防 :添加限制條件,破壞產生死鎖的條件(四個必要條件中的一兩個)
- 避免 :動態檢查,防止系統進入不安全狀態。銀行家算法
- 忽略 :鴕鳥策略
- 檢測解除:允許死鎖,但(不)定期檢測死鎖並解除
死鎖檢測:(死鎖定理:)狀態S爲死鎖狀態的充要條件是:當且僅當S狀態的資源分配圖是不可完全簡化的。
死鎖解除:撤銷進程、資源剝奪、進程回退
★ 安全性算法
★ 銀行家算法
設計思想:當用戶申請一組資源時,系統必須做出判斷:如果把這些資源分出去,系統是否還處於安全狀態。若是,就可以分配這些資源;否則,暫時不分配,阻塞進程。
銀行家算法的使用:
(1)首先根據安全性算法判斷初始時刻系統是否處於安全狀態,如果是,則繼續往下進行。
(2)當某進程請求資源時,根據銀行家算法判斷是否對其分配資源。
(3)循環執行(2)。直到所有進程都順利完成。
★哲學家就餐問題
方案一:爲餐叉編號;就餐前,先取用編號較低的餐叉,再取用編號較高的餐叉;就餐畢,先放下編號較高的餐叉,再放下編號較低的餐叉。
方案二:爲哲學家編號;奇數號的哲學家必須首先拿左邊的餐叉;偶數號的哲學家必須首先拿右邊的餐叉。
方案三:引入一個餐廳服務生,哲學家必須經過他的允許才能拿起餐叉;最多允許4個哲學家同時進食。
方案四:僅當哲學家的左右手筷子都拿起時才允許進餐。多個臨界資源,要麼全部分配,要麼一個都不分配。