1. 程式人生 > >第二章 程序管理(2)

第二章 程序管理(2)

1. 程序同步的基本概念
(1)程序同步的主要任務
使併發執行的諸程序之間能有效地共享資源和相互合作,從而使程式的執行具有可再現性。
(2)臨界資源
一次僅允許一個程序使用的資源。
*理解同步
互斥:在作業系統中,當一個程序進入臨界區使用臨界資源時,另一個程序必須等待,直到佔用臨界資源的程序退出臨界區,我們稱程序之間的這種相互制約關係為“互斥”。
*同步:*多個相互合作的程序,在一些關鍵點上可能需要互相等待或互相交換資訊,這種相互制約關係稱為程序同步關係。可理解為“有序”。
(3)臨界區
每個程序中訪問臨界資源的那段程式碼叫臨界區。
為了正確同步,對臨界區的程式碼要增加控制
在這裡插入圖片描述
進入區:對欲訪問的臨界資源進行檢。若此刻未被訪問,設正在訪問的標誌
臨界區:訪問臨界資源的程式碼。
退出區:將正在訪問的標誌恢復為未被訪問的標誌
剩餘區:其餘部分
(4)同步機制應遵循的規則


1)空閒讓進:資源使用最基本原則
2)忙則等待:保證互斥
3)有限等待:合適時被喚醒防止死等
4)讓權等待:能主動釋放CPU防止忙等
(5)硬體同步機制
許多計算機提供一些特殊的硬體指令,允許對一個字中的內容進行檢測和修正,或對兩個字的內容進行交換。利用這些特殊指令解決臨界區問題。
進入臨界區往往跟其標誌有關,可將標誌看做一個鎖,“鎖開”進入並關鎖,“鎖關”必須等待,初始時鎖是開啟的。
①關中斷
進入鎖測試前關閉中斷,直到完成鎖測試並上鎖後才能開啟中斷。程序在臨界區執行期間,系統不響應中斷,從而不引發排程。
缺點:
濫用風險
關中斷時間過長會影響效率,限制CPU交叉執行能力
不適用於多CPU系統

②Test-and-Set指令

boolean TS(boolean *lock)
{
	Boolean old;
	old=*lock;
	*lock=TRUE;
	return old;
}

為一個臨界資源設定一布林變數lock,初值為false

do{
   …
   while TS(&lock)  ;
   critical section;
   lock=FALSE;
   remainder section;
}while(TRUE);

③利用Swap指令實現程序互斥
對換指令(intel 80x86中稱XCHG指令),用於交換兩個位元組的內容

void swap(boolean *a, boolean *b)
{boolean temp;
  temp=*a;
  *a=*b;
  *b=temp;	 
}

為臨界資源設定一個全域性布林變數lock=false。每個程序一個區域性布林變數key。

do{
    key=TRUE;
    do{
     swap(&lock,&key);
}while(key!=FALSE);
   // 臨界區操作; 
     lock=FALSE;
     //剩餘區; 
     }while(TRUE);

2. 訊號量機制
(1) 整型訊號量
訊號量定義為一個整型量;根據初始情況賦相應的值;僅能通過兩個原子操作來訪問。
P操作

wait(S):	 
While S<=0 do no-op; 
S:=S-1;

V操作

signal(S):	  
S:=S+1;

(2) 記錄型訊號量
整型訊號量符合“有限等待”原則
signal釋放資源後,當CPU被分配給等待程序後,等待程序仍可繼續執行,可以符合“有限等待”。
但整型訊號量不符合“讓權等待”原則
整型訊號量的wait操作,當s ≤0時,當前程序會佔著CPU不斷測試;
訊號量原語不能被打斷,這個佔有CPU的程序會一直不斷的佔據CPU迴圈下去,陷入忙等。
改進:條件不符時應能夠主動放棄CPU
新問題:放棄CPU的程序進入阻塞佇列:因等待某訊號量而放棄CPU的等待程序會有“若干”個,需將它們組織管理起來,並在合適的時候喚醒。

#訊號量結構資訊發生變化
不僅要有值的處理,還有佇列的處理。
此時形成記錄型資料結構,包括兩部分:
整型變數value(代表資源數目)
程序連結串列L(連結所有等待程序):
程式碼描述:

type  Semaphore=record
	value:integer;
	L:list  of  PCB;
end; 

操作:S.Value,S.L
Value>0,表示當前可用資源的數量;
Value≤0,其絕對值表示等待使用該資源的程序數,即在該訊號量佇列上排隊的PCB的個數。

#P、V操作也有所變化
P操作

wait():
    S.value = S.value - 1;
    if  S.value < 0  then  block(S,L)

V操作

signal():
    S.value = S.value + 1;
    if  S.value <= 0 then wakeup(S,L)

• 定義訊號量semaphore代表可用資源實體的數量,又叫訊號燈。
• 當≥0,代表可供併發程序使用的資源實體數
• 當<0,表示正在等待使用該資源的程序數。
建立一個訊號量必須經過說明,包括
• 訊號量所代表的意義
• 賦初值
• 建立相應的資料結構,以便指向等待使用臨界區的程序。
除初值外,訊號量的值僅能由標準原子操作P、V操作來改變。 PV操作是荷蘭語通過和釋放的意思。
(3)訊號量的基本應用
1)實現程序互斥
設定一互斥訊號量mutex,初值為1。
程序i:

P(mutex);
critical section  //操作共享資源R
V(mutex)
remainder section

互斥訊號量注意點:
1. 互斥訊號量mutex初值為1;
2. 每個程序中將臨界區程式碼置於P(mutex)和V(mutex)原語之間
3. 必須成對使用P和V原語(在同一程序中),不能次序錯誤、重複或遺漏:
遺漏P原語則不能保證互斥訪問
遺漏V原語則不能在使用臨界資源之後將其釋放(給其他等待的程序);

2) 實現程序間的前驅關係(有序)
前趨關係:併發執行的程序P1和P2中,分別有程式碼C1和C2,要求C1要在C2開始前完成;
為每對前趨關係設定一個同步訊號量S12,並賦初值為0。則只有V操作所在程序獲得cpu時能執行

P1 : C1 ;signal(S);
P2 : wait(S);C2 ;

控制同步順序的注意點
訊號量值為0的點是限制的關鍵所在,成對使用P和V原語(在有先後關係的兩個程序中),不能次序錯誤、重複或遺漏,否則同步順序出錯。
(4) AND型訊號量
出現原因:一些應用往往需要兩個或多個共享資源,而不是前述的一個資源。程序同時要求的共享資源越多,發生死鎖可能性越大。
在這裡插入圖片描述
解決思想:
一次性分配給程序所需資源,用完一起釋放。Wait操作時對它所有需要的資源都要判斷,有AND條件,故稱“AND同步”、“同時wait”。

Swait(S1, S2, …, Sn)
    if (S1 >=1 and … and Sn>=1 )then
       for i:=1 to n do
        Si:= Si -1 ;
        endfor 
    else

將程序阻塞在第一個不能滿足資源訊號量的佇列中

  endif 
Ssignal(S1, S2, …, Sn)
    for i:=1 to n do
       Si:= Si +1 ;
   // 喚醒所以與si相關的阻塞程序
    endfor    

(5) 訊號量集
**引入原因:**每次只能獲得或釋放一個單位的資源,低效;某些時候資源分配有下限的限制;
修改:在大於可分配設定的下界值t前提下,每次可分配d個。

Swait(S1, t1, d1, …, Sn, tn, dn)
if S1>= t1 and … and Sn>= tn then
for i:=1 to n do
Si:= Si - di ;
endfor 
else
…
endif 
Ssignal(S1, d1, …, Sn, dn)
 for i:=1 to n do
  Si:= Si +di ;
    ….
  endfor 

訊號量集的一個特例
只有一個訊號量S的幾種特殊情況:
①Swait(S, d, d),,允許每次申請d個資源,若現有資源數少於d,不予分配。
②Swait(S, 1, 1),蛻化為一般的記錄型訊號量,一次申請一個,至多分配一個(S>1時可計數,或S=1時可控制互斥)。
③Swait(S, 1, 0),當S>=1時,允許多個程序進入某特定區,當S變為0後,阻止任何程序進入特定區,相當於可控開關。並不對S資源的數量產生影響。