操作系統——2.併發與進程

第二章 併發與進程

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個哲學家同時進食。

方案四:僅當哲學家的左右手筷子都拿起時才允許進餐。多個臨界資源,要麼全部分配,要麼一個都不分配。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章