操作系统第二章 进程管理
寫在前面:本文參考王道論壇的 操作系統考研復習指導單科書
文章目錄
- 第二章 進程管理
- 進程同步
- 讀者寫者問題
- 哲學家就餐問題
- 練習題
- 哲學家就餐:加碗(2019真題)
- 既是生產者又是消費者
- 和尚取水(生產者-消費者問題)
- 三個合作進程(同步:前驅圖)
- 死鎖
- 死鎖預防
- 死鎖避免(銀行家算法)
- 死鎖檢測與解除
第二章 進程管理
進程同步
信號量用于實現進程間的同步和互斥訪問。
讀者寫者問題
模型:讀寫之間互斥,寫寫之間互斥;讀讀不互斥。
關鍵特征:互斥訪問的計數器count。
1)關系分析
寫者和任何人都是互斥的,讀者和讀者不存在互斥關系。
2)思路整理
共有兩個進程,讀者reader()和寫者writer().
- 寫者:因為和任何進程互斥,只要P、V操作即可。
- 讀者:互斥信號量rw實現讀寫互斥;為了實現讀者間同時訪問,創建變量count,用于統計正在讀共享文件的讀者數量。只有第一個讀者可以P(rw);只有最后一個讀者可以V(rw); 使用互斥信號量mutex用于不同讀者進程互斥的訪問count變量.
- 寫優先
- 設置互斥信號量w用于控制寫優先。讀進程和寫進程在進入后首先P(w),表示在無寫進程的時候進入,實現寫進程優先。
使用信號量實現進程的互斥和同步:
#include<stdio.h>/* typedef struct{int value;struct process *L; }semaphore;*/ #define semaphore intsemaphore rw = 1; // 讀者和寫者互斥訪問 int count = 0; // 統計正在讀共享文件的讀者數量 semaphore mutex = 1; // 多個讀進程互斥的訪問count變量 semaphore w = 1; // 用于實現寫優先void writer(){while (1){P(w); // 在無寫請求的時候進入P(rw); //互斥訪問共享文件// writingR(rw);V(w); //恢復對共享文件的訪問}}void reader_write_first(){while(1){P(w); // 在沒有寫請求的時候進入P(mutex);if(count == 0)P(rw);count ++;V(mutex);V(w); // 恢復對共享文件的訪問// readingP(mutex);count --;if(count == 0)V(rw);V(mutex);} }哲學家就餐問題
哲學家問題的一種解法
思路一:至多允許n-1個哲學家同時就餐
semaphore Max = n - 1; // 最多允許n -1 個人同時吃飯 semaphore chopsticks[n];for(int i = 0; i < n; i ++)chopsticks[i] = 1;Pi(){P(Max);P(chopsticks[i]); // 拿左手邊的筷子P(chopsticks[(i+1)%n]); // 拿右手邊的筷子//eatingV(Max);V(chopsticks[i]);V(chopsticks[(i+1)%n]);// thinking }練習題
哲學家就餐:加碗(2019真題)
思路:使用互斥信號量來控制哲學家拿筷子。取互斥信號量bowl取筷子(n)和碗(m)兩者的最小值。why?
-
當m < n時,碗的數量少,此時P(bowl) 和V(bowl)可以起到限制作用。此時,碗的數量m相當于普通的哲學家問題解法里面的Max,即Max = m;
-
當n ≥ m時,碗多,此時P(bowl) 和V(bowl)不起作用。問題退化為普通的哲學家就餐問題,此時Max = n - 1;
綜上,取semaphore bowl = min(m, n- 1);
信號量偽代碼:
#include<stdio.h>/* typedef struct{int value;struct process *L; }semaphore;*/ #define semaphore int #define n 3 #define m 5semaphore chopsticks[n]; semaphore bowl = min(n - 1,m);void Pi(){for(int i = 0; i < n; i ++)chopsticks[i] = 1; // 互斥信號量全部初始化為1P(bowl);P(chopsticks[i]);P(chopsticks[(i+1)%n]);// eatingV(chopsticks[i]);V(chopsticks[(i+1)%n]);V(bowl);// thinking }既是生產者又是消費者
解答
#include<stdio.h>/* typedef struct{int value;struct process *L; }semaphore;*/ #define semaphore int semaphore mutex = 1;// 互斥訪問緩沖區 semaphore full = 0; // 緩沖區產品的數量 semaphore empty = 1; // 緩沖區空格的數量//P是生產者 void P(){while(1){P(empty);P(mutex);// produce oneV(mutex);V(full);} }// Q是消費者 void Q(){while(1){P(full);P(mutex);// consume oneQ(mutex);Q(empty);} }//R 既是生產者又是消費者 void R(){// 執行producer的職能if(empty == 1){P(empty);P(mutex);// produce one;V(mutex);V(full);}//執行consumer的職能if(full == 1){P(full);P(mutex);// consume oneV(mutex);V(empty);} }和尚取水(生產者-消費者問題)
信號量代碼
#include<stdio.h>/* typedef struct{int value;struct process *L; }semaphore;*/ #define semaphore intsemaphore well = 1; //用于互斥訪問水井 semaphore vat = 1; // 用于互斥訪問水缸 semaphore empty = 10; // 表示水缸內還可以容納的水的桶數 semaphore full = 0; // 表示水缸中水的桶數 semaphore pail = 3; // 表示有多少個水桶可以用void old_monk(){P(full); // 老和尚取水后,水缸中水的數量--P(pail);P(vat);// 從水缸(vat)中取一桶水V(vat);V(empty); // 取完水后,水缸剩余空間++// 喝水V(pail); } /* 注意P操作的先后順序:先確認水缸還有空余位置,再去拿桶,再打水。*/void little_monk(){P(empty); // 水缸中剩余空間-- P(pail);P(well);// 從水井(well)中打一桶水V(well);P(vat);// 倒入水缸(vat)V(vat);V(full); // 水缸中水量++v(pail); }本題批注:
連續多個P操作連在一起的時候,檢查可能會發生死鎖。本題如果先P(pail),再P(empty);就會發生死鎖。pail是水桶,empty是水缸內剩余空間能容納的水的桶數
三個合作進程(同步:前驅圖)
分析:
各個進程的任務:
進程同步:
注意:進程同步前V后P的使用,亦即在前的進程執行完后V(某信號量);,而在后的進程執行前P(某信號量);
下面是三個進程的執行順序,故而需要兩個同步信號量。
此題有前驅圖的感覺。前驅圖使用信號量進行同步,所以就不需要再使用另外的互斥信號量mutex了。
死鎖
死鎖v.s. 饑餓 v.s. 死循環
- 死鎖:各進程相互等待對方手里的資源,導致各進程都阻塞
- 饑餓:某進程長時間得不到某種資源,無法向前推進。比如短進程優先(SPF)算法中,長進程可能一直無法運行,“饑餓”
- 死循環:某進程執行過程中一直跳不出某個循環的現象
死鎖和饑餓是操作系統要解決的問題,死循環是應用程序員要解決的問題。
死鎖預防
死鎖避免(銀行家算法)
死鎖檢測與解除
系統為進程分配資源時不采取任何措施,而在具體分配過程中提供死鎖檢測和解除的手段。
資源分配圖:是一個有向圖,用于表示某時刻系統資源與進程之間的關系。
圓圈代表進程,方框代表一類資源,方框內圓圈個數代表該類資源的個數。
死鎖的知識結構
總結
以上是生活随笔為你收集整理的操作系统第二章 进程管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年通信网络基础期末复习
- 下一篇: 对函数指针与typedef的理解:typ