1. 程式人生 > >【作業系統】第二章 程序管理2

【作業系統】第二章 程序管理2

1.經典同步問題
(1)生產者與消費者問題
buffer: array [ 0, …, n-1] of item;
in, out: integer :=0, 0;
Var mutex, empty, full: semaphore :=1, n, 0;
producer :
repeat

produce an item in nexp;

wait(empty);//表示緩衝池中空緩衝池的數量,當empty>0時,生產者申請mutex,執行下面的操作,釋放mutex後,下一個生產者才能進行。如果空緩衝池的數量為0,生產者不能再放產品,,被阻塞,等待消費者取後,才有可能搶到資源然後執行。
wait(mutex);

///互斥訊號量mutex,保證生產者,消費者對緩衝池的互斥使用,與wait(empty)順序不可顛倒
buffer(in):=nexp;
in:=(in+1) mod n;
signal(mutex);
signal(full);//full表示滿緩衝池的數量,empty與full在值等於0的點上是控制順序的關鍵
until false;

consumer :
repeat
wait(full);//當full為0時,,沒有產品。消費者取得時候,full=-1,被阻塞,只有等生產者放入產品後,才能取
wait(mutex);
nextc:=buffer(out);
out:=(out+1) mod n;
signal(mutex);


signal(empty);
consume the item in nexc;
until false;

(2)哲學家進餐問題
1)記錄型訊號量解決哲學家進餐問題
只有拿到兩根筷子才能進餐,不可能五個人同時進餐。如果每個人都同時拿起左邊的筷子,再拿右筷子時就會發生死鎖。
解決方法:
至多隻允許有四位哲學家同時去拿左邊的筷子
semaphore chopstick[5]={1,1,1,1,1};
semahpore eat=4;//計數控制
do{
wait(eat);
wait(chopstick[ i ]);
wait(chopstick[ ( i +1) mod 5] );

 eat;
 …
      signal(chopstick[ i ]);
      signal(chopstick[ ( i +1) mod 5] );
      signal(eat);
 …
 think;}while(true)

僅當哲學家的左右筷子均可用時,才允許他拿起筷子進餐。

規定奇數號哲學家先拿他左邊的筷子,然後再去拿右邊的筷子;偶數號哲學家則相反。保證總會有一個哲學家能同時獲得兩隻筷子而進餐。
2)利用AND訊號量機制解決哲學家進餐問題
semaphore chopstick[5]={1,1,1,1,1};
do{

think

Swait(chopstick[(i+1)%5],chopstick[i]);

eat

Singal(chopstick[(i+1)%5],chopstick[i]);
}while[true];
(3)讀者寫者問題
//讀者優先 :若讀者先佔有互斥訊號量,只有最後一個讀者離開,計數降為0時才釋放訊號量,導致寫者弱勢
semaphore rmutex=1,wmutex=1;
int readcount=0;
void reader(){
do{
wait(rmutex); //讀者之間的互斥訊號量,使第一個讀者進來競爭資源,其餘讀者會阻塞
if(readcount0) wait(wmutex);//判斷是否為第一人,如果是,與寫者競爭(讀者與寫者之間的互斥)
readcount++;
signal(rmutex);

perform read operation;

wait(rmutex);
readcount–;
if(readcount
0) signal(wmutex);
signal(rmutex);
}while(true);
}
void Writer()
{
do{
wait(wmutex);
perform write operation;
signal(wmutex);
}while(true);
}
void main()
{
cobegin
Reader();
Writer();
coend;
}
//寫者優先 寫者先佔有某訊號後,直到最後一個寫者走完才釋放該訊號,讀者才能進入
semaphore s=1,rmutex=1,mutex=1;
readcount=0;
writecount=0;
//互斥訊號量S,讀者和寫者都爭搶該訊號;第1個寫者申請S,其他寫者不需要申請S;最後一個寫者離開時才釋放訊號量S.一旦寫者先申請到了S,則所有的讀者只能等待寫者都走完才可進入共享讀。而多個寫者通過S後,仍要爭搶wmutex訊號以完成互斥的寫入

讀者:
wait(s);
wait(rmutex);
if Readcount=0 then wait(wmutex);
Readcount +1;
signal(rmutex);
signal(s)
讀操作
wait(rmutex);
Readcount -1;
if Readcount=0 then signal(wmutex);
signal(rmutex)

寫者:
wait(mutex);
if writecount=0 then wait(s);
writecount+1;
signal(mutex);
wait(wmutex);
寫入檔案;
signal(wmutex);
wait(mutex);
writecount-1;
if writecount=0 then signal(s);
signal(mutex);
(4)黑白棋子問題
兩個人下棋,一方執黑棋,一方執白棋。要求雙方輪流下子。給出兩種情況的解決辦法:
1)執黑子一方先下
seamphore bfg=1,wfg=0;
void main()
{
black();
write();
}
void black()
{
while(true){
wait(bfg);
if whereput()
{
put a black qizi;
signal(wfg);
}else
{
signal(wfg);
break;
}
}
void white()
{
while(true){
wait(wfg);
put a white qizi;
signal(bfg);
}
}
2)雙方都可以先下,誰先搶到棋盤誰先下。然後開始輪流下子。
seamphore bfg=1,wfg=0,m=1;
boolean fg=F;
void main()
{
black();
write();
}
void black()
{
wait(m);
if(!fg)
{
bfg=1;wfg=0;fg=T;
}
signal(m);
while(true){
wait(bfg);
if whereput()
{
put a black qizi;
signal(wfg);
}else
{
signal(wfg);
break;
}
}
void white()
{
wait(m);
if(!fg)
{
bfg=0;wfg=1;
fg=T;
}
signal(m);
while(true){
wait(wfg);
put a white qizi;
signal(bfg);
}
}
2.管程(monitor)機制
(1)需要封裝:
多程序需訪問的變數
對變數做的操作
(2)管程的組成
一組區域性變數
對區域性變數操作的一組過程
對區域性變數進行初始化的語句
(3)管程特點
任何程序只能通過呼叫管程提供的過程入口才能進入管程訪問共享資料;
任何時刻,僅允許一個程序在管程中執行某個內部過程。
(4)管程如何實現同步
對共享變數互斥操作:
管程的特點直接實現了該要求,程序一次一個進入管程呼叫內部過程操作共享變數。
管程的互斥訪問完全由編譯程式在編譯時自動添上,無須程式設計師關心,能保證正確。
操作的同步控制:
靠條件變數的操作管理實現。
進入管程但不能獲取資源操作的過程將阻塞,並在滿足條件時被喚醒執行。
3.程序通訊的型別
(1)高階通訊機制可歸結為四大類
a.共享儲存器系統(操作儲存區方式)
相互通訊的程序共享某些資料結構或共享儲存區,程序之間能夠通過這些空間進行通訊。
基於共享資料結構的通訊方式(低階)
基於共享儲存區的通訊方式(高階)

b.訊息傳遞系統(發–收方式)
c.管道通訊(中間檔案方式)
d.Client-Server system
(2)訊息傳遞通訊的實現方法
1)直接通訊方式
通常利用系統通訊命令(原語):
Send(Receiver, message);
Receive(Sender, message);
2)間接通訊方式
基於共享資料結構的實體用來暫存傳送給目標程序的訊息;接收程序則從該實體中,取出對方傳送給自己的訊息。通常把這種實體稱為信箱。
4.執行緒的屬性
多執行緒OS中,一個程序包括多個執行緒,每個執行緒都是利用CPU的基本單位。
(1)TCB管理的資訊:
狀態引數
識別符號、執行狀態、優先順序、暫存器狀態、堆疊、專有儲存器、訊號遮蔽等。
執行狀態
執行、就緒、阻塞
(2)同步和通訊機制
互斥鎖、條件變數、條件變數
5.執行緒的實現方式
核心執行緒KST(kernel-level thread)
使用者執行緒ULT(user-level thread)
組合方式