文章目錄
- 6.經典進程同步問題
- 6.1 生產者-消費者問題 (既有同步又有互斥)
- 6.2 讀者-寫者問題
- 6.3 哲學家進餐問題
- 6.4理發師問題
- 7. 進程之間通信
- 7.1 共享存儲區
- 7.2 消息傳遞
- 7.3 管道
- 8.線程
- 8.1 線程的實現機制
- 9 進程調度
- 9.1 調度方式
- 9.2 常見算法
- 先來先服務 FCFS
- 短進程優先 SPN
- 最高相應比優先算法
- 時間片輪轉 RR
- 基于優先級的調度
- 多級反饋隊列
- 10 死鎖
- 10.1 基本概念
- 資源分類
- 10.2 如何處理死鎖
- 10.2.1 死鎖檢測
- 10.2.2 何時檢測
6.經典進程同步問題
6.1 生產者-消費者問題 (既有同步又有互斥)
生產者往緩沖區寫數據,滿了的話就不能寫了
消費者從緩沖區取數據,空的話就不能取了
一次只能有一個生產者或消費者取讀數據
總結要求
(1)不能向滿的緩存區寫數據
(2)不能向空的緩存區取數據
(3)任何時刻,僅允許一個1個生成者或1個消費者訪問
? 意味著消費者之間互斥,生成者之間互斥,消費者和生產者之間互斥
full:記錄緩沖區中非空的槽數,初始值=0
empty:記錄緩沖區中空的槽數,初始值=N
mutex:確保進程不同時訪問緩沖區,初始值=1
解決(1)(2)
void producer(void){while (True) {produce(); //生產1項P(empty); //申請1個空槽P(mutex); //請求進入臨界區append(); //加入緩沖區V(mutex); //離開臨界區V(full); //遞增非空槽}
}void consumer(void){while (TRUE) {P(full); //申請1個非空槽P(mutex); //申請進入臨界區remove(); //從緩沖區移出1項V(mutex); //離開臨界區V(empty); //遞增空槽數consume(); //消費數據}
}
解決死鎖問題
6.2 讀者-寫者問題
多個Reader進程,多個Writer進程,共享文件F
要求:
允許多個Reader進程同時讀文件
不允許任何一個Writer進程與其他進程同時訪問(讀或寫)文件
我的方案
read_count=N 初始值N,空額的值
write_count=0
void reader(void){while (True) {P(read_count)if(writer==0)read();//讀操作V(read_count)P(write_count)read();V(write_count)}
}void writer(void){while (True) {P(write_count)write();V(write_count)}
}
標答
write
WriteMutex = 0 讀寫操作的互斥訪問
Rcoun = 0 正在讀操作的讀者數目
CountMutex = 0 讀者計數的互斥訪問
void reader(void){while (True) {P(CountMutex);if (Rcount == 0)P(WriteMutex);++Rcount;V(CountMutex);read;P(CountMutex);--Rcount;if (Rcount == 0)V(WriteMutex);V(CountMutex);}
}void writer(void){while (True) {P(WriteMutex);write;V(WriteMutex);}
}
6.3 哲學家進餐問題
6.4理發師問題
注意對于共享變量,一定要加PV臨界操作
7. 進程之間通信
P,V操作實現的是進程之間的低級通信,所以P,V操作是低級通訊原語,即不能傳遞大量的信息
所以我們引入進程間高級通訊方式
7.1 共享存儲區
相互通信的進程間設有公共的內存區,每個進程既可向該公共內存中寫,也可從公共內存中讀,通過這種方式實現進程間的信息交換。
把同一個物理內存區域同時映射到多個進程的內存地址空間的通信機制
7.2 消息傳遞
源進程發送消息,目的進程接受消息。所謂消息,就是一組數據。
(1)消息隊列(message Queue)或消息緩沖
發送者發消息到一個消息隊列中;
接收者從相應的消息隊列中取消息。
消息隊列所占的空間從系統的公用緩沖區中申請得到。
(2)郵箱(mailbox)
發送者發消息到郵箱,接收者從郵箱取消息。
郵箱是一種中間實體,一般用于非實時通信。
7.3 管道
首創于Unix。用于連接一個讀進程、一個寫進程,以實現它們之間通信的共享文件,稱為pipe文件。
管道分為下列2種:
有名管道
無名管道
8.線程
為什么引入線程
線程是進程的1條執行路徑。
1個進程可以有多個線程,其中至少有1個主線程(primary thread)。
1個進程內的多個線程在同一個地址空間內(共享該進程的地址空間)。
每個線程有自己的線程控制塊TCB(Thread Control Block),包含自己的堆棧和狀態信息。TCB比PCB小得多。
8.1 線程的實現機制
用戶級線程
? 由在用戶空間執行的線程庫來實現,OS對此一無所知。
線程庫提供線程創建、撤消、上下文切換、通信、調度等功能。
? 用戶級線程是自己實現的線程創建,刪除
? 但是這樣的話操作系統分配的是進程為單位的,容易阻塞
? 但是性能高,無需陷入內核
核心級線程
? 用戶級線程是自己實現的線程創建,刪除
? 但是這樣的話操作系統分配的是線程為單位的
? 但是性能低,需要陷入內核
進程和線程是操作系統中用于實現并發執行的兩個基本概念,它們之間有許多重要區別,包括以下幾點:
-
定義:
- 進程(Process)是一個獨立的執行單元,擁有獨立的內存空間和系統資源,它代表了一個正在運行的程序的實例。每個進程都有自己的地址空間,堆棧和數據段,相互之間不共享這些資源。
- 線程(Thread)是進程內的一個輕量級執行單元,線程共享進程的地址空間和系統資源,包括堆棧和文件描述符。多個線程可以在同一進程中并發執行,它們之間共享相同的內存空間。
-
創建和銷毀開銷:
- 進程的創建和銷毀通常比較耗費系統資源,因為每個進程都有獨立的內存空間,需要進行全新的資源分配和銷毀。
- 線程的創建和銷毀相對較輕量,因為它們共享進程的資源。創建一個線程通常比創建一個新進程要快速和經濟。
-
通信:
- 進程之間通信通常需要使用進程間通信(Inter-Process Communication,IPC)機制,例如管道、消息隊列、共享內存等,來傳遞數據和信息。
- 線程之間通信可以更容易地實現,因為它們共享相同的內存空間。線程可以通過共享變量等方式直接進行通信。
-
并發性和并行性:
- 進程通常具有更高的并發性,因為不同進程之間相互獨立,可以在不同的處理器上并行執行。多進程可以更好地利用多核處理器。
- 線程在同一進程內并發執行,它們共享進程的資源,因此在多核處理器上并行執行的程度有限。但線程之間的切換比進程切換更快,因為不涉及進程資源的切換。
-
安全性:
- 由于線程共享進程的內存空間,因此多個線程之間的錯誤可能更容易導致進程崩潰或數據損壞。
- 進程之間的安全性更高,因為它們擁有獨立的內存空間,一個進程的錯誤通常不會影響其他進程。
-
編程模型:
- 多進程編程相對較復雜,因為需要處理進程間通信和同步問題。
- 多線程編程相對較簡單,因為線程之間共享數據,但需要小心處理共享資源的同步問題。
9 進程調度
為什么進程調度
多個進程就緒時候,OS決定先執行哪一個
我們進程調度要達到的目的
? CPU利用率高,吞吐量大,周轉時間少,等待時間短,公平
? 很多時候都是在權衡!很多時候很難兼顧所有的目的
什么時候會切換進程呢?
? 硬件中斷,進程異常,或者該進程請求IO,這些都會讓CPU閑下來,我們就要給CPU找活干了
一些概念
- 周轉時間 = 作業完成時刻 - 作業到達時刻
- 帶權周轉時間 = 周轉時間 / 服務時間
- 平均周轉時間 = 作業周轉總時間 / 作業個數
- 平均帶權周轉時間 = 帶權周轉總時間 / 作業個數
9.1 調度方式
非搶占方式
? 一旦某進程被調度,直到完成或因某事件而阻塞,才會切換到其他進程
搶占方式
? 允許暫停正在運行的進程,切換到其他進程
搶占原則:
? 時間片原則:時間片到時搶占
? 優先級原則:優先級高者到時搶占
9.2 常見算法
先來先服務 FCFS
按照進程就緒的先后次序來調度進程,非搶占式方式
優點:實現簡單
缺點:
(1)平均等待時間波動很大
短進程、長進程到達時間是隨機的
(2)有利于CPU繁忙型進程,不利于I/O繁忙型進程
(3)有利于長進程,不利于短進程
短進程優先 SPN
最高相應比優先算法
時間片輪轉 RR
將所有的就緒進程按FCFS原則排成一個隊列,
規定一個時間片為進程每次使用CPU的最長時間,
每次選擇隊首進程運行,
當時間片到時,剝奪該進程的運行,將其排在隊尾
基于優先級的調度
多級反饋隊列
10 死鎖
10.1 基本概念
死鎖
一個進程集合中的每個進程都在等待只能由該集合中的其它進程才能引發的事件,這種狀態稱作死鎖。一組競爭系統資源的進程由于相互等待而出現“永久”阻塞。
例如,2個進程A、B,都需要資源R1、R2
若A:擁有R1,申請R2
若B:擁有R2,申請R1
如何?
資源分類
可重用資源
資源不能被刪除且在任何時刻只能有一個進程使用
進程釋放資源后,其他進程可重用
消耗資源
10.2 如何處理死鎖
由OS處理
? 檢測死鎖并恢復
? 分配資源時避免死鎖
? 假裝沒看見(鴕鳥策略):多數OS對待死鎖的策略
? 死鎖了怎么辦,開機重啟
由應用程序本身預防死鎖
?
實際中檢測死鎖恢復是可能的,但是代價太大
10.2.1 死鎖檢測
E[M]:總資源數;E[i]:資源i的個數
A[M]:當前可用資源數;A[i]:資源i的可用數
C[N][M]:當前分配矩陣;C[i][j]:進程i對資源j的占有數
? 第i行是進程i當前占有的資源數
R[N][M]:申請矩陣;R[i][j]:進程i對資源j的申請數
? 第i行是進程i申請的資源數
F[N]:進程標記;F[i]取0/1,為1表示進程i能夠執行
算法
? 看當前是否有進程可以執行,可以執行的話,該進程F[N]設置為1,同時釋放他的資源
? 依次進行
? 兩種情況
? 一, 所有進程都可以執行,則不死鎖
? 二,存在某一種情況所有的進程都無法執行,則死鎖
10.2.2 何時檢測
1)每當有資源請求時;
2)周期性檢測;
3)每當CPU的使用率降到某一閾值時。
死鎖檢測會占用大量的CPU時間