進程同步與信號量(李治軍操作系統課筆記6)

臨界區:一次只允許一個進程進入

爲什麼需要臨界區?兩個生產者因競爭資源會產生隨機的執行順序,造成信號量的修改不當,信號量語義錯誤,所以需要保護信號量。

臨界區代碼的保護原則:
1、基本原則——互斥
2、有空讓進
3、有限等待

臨界區保護方法

1、輪換法:
在這裏插入圖片描述
但是,若P1被什麼阻塞了,而P0結束了之後又不能繼續進入臨界區,導致兩個都不在臨界區。

2、標記法:
在這裏插入圖片描述
但是,因爲變量不共享,所以看不到對方的標記。若如上圖所示執行順序,則會導致兩個都不在臨界區。

3、Peterson
在這裏插入圖片描述
其實就是在上面一種方法的基礎上加上了一個共享變量(非共享+共享)
雖然turn是共享變量,但是不需要保護
可驗證Peterson算法滿足臨界區三條原則

4、多個進程?——麪包店算法
在這裏插入圖片描述
注意while(choosing);
也滿足三條原則:
在這裏插入圖片描述
5、臨界區的另一類保護解法:開關中斷
在這裏插入圖片描述
cli=clear interuption ; sti=set interuption
原理是,在進入區阻止調度schedule的發生,而調度是因爲中斷,所以就是關閉中斷
但在多CPU上不行,因爲無法控制關閉所有cpu上的中斷

6、硬件原子法
在這裏插入圖片描述
原子指令(一次執行,要不不做,做就做完):當TestAndSet得到結果時已經上鎖

總結:

臨界區域保護信號量的語義正確:麪包店算法、開關中斷、硬件原子……
信號量實現進程同步

進入睡眠的方式

有if和while兩種進入睡眠方式,if非常直白,下面介紹while:
在這裏插入圖片描述
如何理解while?
先看sleep_on函數:
在這裏插入圖片描述
睡眠的實質,就是把自己寫到阻塞隊列上+改變自己的狀態(也就是圈圈裏的內容) ,然後再調用schedule
事實上,圈圈裏的內容形成了一個睡眠隊列:
在這裏插入圖片描述
tmp是局部變量,存儲在當前進程的內核棧中,所以可以通過當前的task_struct找到內核棧中的tmp;tmp指向的是下一個task_struct,又可以通過下一個task_struct找到tmp,指向下下一個……由此形成隊列

喚醒函數:
在這裏插入圖片描述
進程被喚醒後要從當時進入sleep的後面一句繼續執行:
在這裏插入圖片描述
也就是if(tmp) tmp->state=0;
因爲tmp指向睡眠隊列中的下一個進程,所以會繼續喚醒隊列中下一個進程

while的好處:一次性全部喚醒,讓schedule來決定switch_to誰,這樣可以不按照先來先後,可以按優先級。

並且優先級最高的執行後,其他被喚醒的進程會繼續上鎖,不會一連串執行:
在這裏插入圖片描述
被喚醒後還要判斷一遍while(),schedule切換到優先級最高的進程,執行bh->b_lock=1,而其他被喚醒的在進行while(bh->b_lock)判斷時,就執行sleep_on了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章