作業系統(7)程式間通訊

笨蛋糕發表於2014-03-06

1、訊號量解決讀者-寫者問題:有兩組併發程式:讀者和寫者,共享檔案F,要求:

1)允許多個讀者同時對檔案執行讀操作。

2)只允許一個寫者對檔案執行寫操作。

3)任何寫者在完成寫操作之前不允許其他讀者或寫者工作。

4)寫者在執行寫操作之前,應讓已有的寫者和讀者全部退出。

單純引入訊號量不能解決此問題,必須引入計數器readcount對讀程式計數,mutex是用於對計數器readcount操作的互斥訊號量,writeblock表示是否允許寫的訊號量。

int readcount = 0;          //讀程式計數

semaphore writeblock, mutex;

writeblock = 1;  mutex = 1;

cobegin 

process reader_i( )   {                    process writer_j( )   { 

      P(mutex);                                         P(writeblock);

      readcount++;                                   {寫檔案};

       if(readcount ==1)                            V(writeblock);

             P(writeblock);                     }

             V(mutex);

             {讀檔案};

             P(mutex);

             readcount --;

             if(readcount == 0)

                 V(writeblock);

             V(mutex);

}

coend

2、訊號量解決理髮師問題:

引入3個訊號量和一個控制變數:控制變數waiting記錄等候理髮的顧客坐的椅子數,初值為0;訊號量customers記錄等候理髮的顧客數,並用於阻塞理髮師程式,其初值為0;訊號量barbers記錄正在等候理髮的顧客數,並用於阻塞顧客程式,其初值為0;訊號量mutex用於互斥,其初值為1;

int waiting = 0;             //等待理髮的顧客坐的椅子數

int CHAIRS = N;              //為顧客準備的椅子數

semaphore customers, barbers, mutex;

customers = 0;  barbers = 0; mutex = 1;

cobegin

process barber( )  {

        while( true)  {

            P(customers);             //判斷是否有顧客,若無顧客,理髮師睡眠

            P(mutex);                   //若有顧客,進入臨界區

            waiting --;                   //等候顧客數減1

            V(barbers);               //理髮師準備為顧客理髮

            V(mutex);                  //退出臨界區

            cut_hair( );                //理髮師正在理髮(非臨界區)

       }

}

process customer_i( )  {

         P(mutex);                        //進入臨界區

         if(waiting<CHAIRS)  {               //判斷是否有空椅子

                waiting ++;                     //等候顧客數加1

                 V(customers);                  //喚醒理髮師

                 V(mutex);                    //退出臨界區

                  P(barbers);               //理髮師忙,顧客坐著等待

                   get_haircut( );           //否則,顧客可以理髮

           }

           else

                   V(mutex);              //人滿了,顧客離開

}

coend

3、管程:屬性有共享性,安全性,互斥性。

基本思路:把分散在各程式中的臨界區集中起來管理,並把共享資源用資料結構抽象表示出來,由於臨界區是訪問共享資源的程式碼段,建立一個“祕書”程式管理到來的訪問,“祕書”每次只讓一個程式來訪。

1)條件變數:一種資料結構,只有在管程中才能被訪問,對管程是全域性的,只能通過兩個原語操作來控制它。

2)wait( ):掛起呼叫程式並釋放管程,直至另一個程式在條件變數上執行signal( )。

3)如果有其他程式因對條件變數執行wait( )而被掛起,便釋放之。如果沒有程式在等待,那麼,訊號不被儲存。

注意:wait操作一般應在signal操作之前發出。

4、程式的通訊方式:

1)訊號:

是一種軟中斷,只能傳送單個訊號而不能傳送資料。訊號處理完畢後,被中斷程式將恢復執行。使用者、核心和程式都能生成訊號請求。由程式執行指令而產生的訊號稱為同步訊號。像擊鍵之類的程式以外的事件所引起的訊號稱為非同步訊號。訊號有一個產生、傳送、捕獲和釋放的過程。

2)管道:

實質是一個共享檔案,即利用輔助儲存器來進行資料通訊。管道是單向的,傳送程式視管道檔案為輸出檔案,以字元流的形式把大量資料送入管道;接收程式視管道檔案為輸入檔案,從管道中接收資料。

3)共享主存:

指在主存中開闢一個公用儲存區,要通訊的程式把自己的虛擬地址空間對映到共享主存區。共享主存的頁面在每個共享程式的頁表中都有頁表項引用,但無須在所有程式的虛存段都有相同的地址。因為不止一個程式可將共享主存對映到自己的虛地址空間中去,讀寫共享主存區的程式碼段通常被認為是臨界區。

4)訊息傳遞

互動式併發程式通過訊號量及PV操作可實現程式的互斥和同步。訊息傳遞的複雜性在於:地址空間的隔離,傳送程式無法將訊息直接複製到接收程式的地址空間中,這項工作只能由作業系統來完成。提供兩條原語send和receive,前者向一個給定的目標程式傳送一條訊息,後者從一個給定的源程式接收一條訊息。為了實現非同步通訊,必須採用間接的通訊方式,程式之間傳送或接收訊息通過一個共享的資料結構——信箱進行,訊息可被理解成信件,每個信箱都有唯一識別符號。

//訊息傳遞機制解決程式互斥問題

create_mailbox(box);

send( box, null);

void Pi( )  {    //i=1,2,...n

        message msg;

        while(true)  {

              receive( box, msg);

              {臨界區};

              send(box, msg);

          }

}

cobegin

    Pi( );

coend

5、程式使用獨佔型資源必須按照以下次序進行:申請資源、使用資源、歸還資源。

死鎖:

兩個程式分別等待對方所佔用的一個資源,於是兩者都不能執行而處於永遠等待狀態。產生死鎖原因很多,例如:程式推進順序不當,PV操作使用不妥,同類資源分配不均或對某些資源的使用未加限制。

解決方法:死鎖防止,死鎖避免,死鎖檢測和恢復。

產生死鎖必定同時保持4個必要條件:

1)互斥條件:系統中存在臨界資源,程式應互斥地使用這些資源。

2)佔有和等待條件:程式在請求資源得不到滿足而等待時,不釋放已佔有的資源。

3)不剝奪條件:已被佔用的資源只能由屬主釋放,不允許被其他程式剝奪。

4)迴圈等待條件:存在迴圈等待鏈,其中,每個程式都在鏈中等待下一個程式所持有的資源,造成這組程式處於永遠等待狀態。

6、銀行家演算法:

系統中的所有程式放入程式集合,在安全狀態下系統收到程式的資源請求後,先把資源試探性地分配給它。現在,系統將剩下的可用資源和程式集合中其他程式還需要的資源數進行比較,找出剩餘資源能滿足最大需求量的程式,從而保證程式執行完畢後並歸還全部資源。這時,把這個程式從程式集合中刪除,歸還其所佔用的所有資源,系統的剩餘資源更多,反覆執行上述步驟。最後,檢查程式集合,若為空則表明本次申請可行,系統處於安全狀態,可以真正實施本次分配;否則,只要程式集合非空,系統便處於不安全狀態,本次資源分配暫不實施,讓申請資源的程式等待。

7、資源分配圖和死鎖定理:

系統定時地執行“死鎖檢測程式”,判斷系統內是否已經出現死鎖,如果檢測到系統已死鎖,在採取措施解除它。實現的難點在於,要確定何時執行死鎖檢測演算法。

注意,在程式-資源分配圖中存在環路並不一定必發生死鎖,因為迴圈等待資源僅是死鎖發生的必要條件,而不是充分條件。

常用的解除系統死鎖方法:

資源剝奪法。程式回退法。程式撤銷法。系統重啟法。

8、互斥物件用於控制共享資源的互斥訪問,在一個時刻,互斥物件只能被一個執行緒使用,其相關API包括:

1)CreateMutex:建立一個互斥物件,返回物件控制程式碼。

2)OpenMutex:開啟並返回一個已存在的互斥物件控制程式碼。

3)ReleaseMutex:釋放對互斥物件的佔用,使之可用。

9、訊號量物件就是資源訊號量,其初始值範圍在0到指定的最大值之間,用於限制併發訪問的執行緒數,其相關API為:

1)CreateSemaphore:建立一個訊號量物件,在輸入引數中指定初始值和最大值,返回物件控制程式碼。

2)OpenSemaphore:開啟並返回一個已存在的訊號量物件控制程式碼。

3)ReleaseSemaphore:釋放對訊號量物件的佔用,使之可用。

10、事件物件相當於觸發器,可用於通知一個或多個執行緒某事件已出現,相關API:

1)CreateEvent:建立一個事件物件,返回物件控制程式碼。

2)OpenEvent:開啟並返回一個已存在的事件物件控制程式碼。

3)SetEvent和PulseEvent:設定所指定的事件物件為可用狀態。

4)ResetEvent:設定所指定的事件物件為不可用狀態。

注意:對於以上三種同步物件,等待操作WaitForSingleObject和WaitForMultipleObject,前者可在指定的時間內等待指定物件轉換為可用狀態;後者可在指定的時間內等待多個物件轉換為可用狀態。


相關文章