2.3 進程間通信
2.3.1 競爭條件
舉個栗子:有兩個進程同時對同一內存或磁盤上的文件進行讀寫,那麽假設進程A先讀了一段,此時內核調度讓進程B進行寫,那麽下一次A讀的就不是原來的數據了。類似這樣的情況,兩個或多個進程同時讀寫某些共享數據,而最後的結果取決於進程運行的精確時序,稱為競爭條件。
2.3.2 臨界區
我們要找出某種途徑來阻止多個進程同時讀寫數據,即以某種手段來確保當一個進程在使用共享數據時,其他進程不能做相同的操作,所以我們需要的是互斥(mutual exclusion)。運用抽象的思想:我們把對內存進行訪問的程序片段稱為臨界區(critical region)。所以一個好的方案要滿足一下的條件:
1.任何兩個進程不能同時進入臨界區 2.不能對cpu速度和數量做任何的假設。
3.臨界區外進行的進程不能阻塞其他進程 4.不能使進程無限期等待進入臨界區。
如下圖:
2.3.3 忙等待的互斥
有幾種實現互斥的方案,如下:
1.屏蔽中斷
當進程進入臨界區時,讓內核不進行上下文的切換,讓cpu單獨為這個進程服務,當然這是最簡單的想法也是最不現實的。
2.鎖(lock)變量
進程有一個共享鎖變量,初始值為0,表示進程可以進入臨界區,然後修改值為1,其他進程想要進入臨界區時先訪問這個鎖變量,如果值為1則切換其他線程。雖然比上一個方法解決了運行多個進程的功能,然而也有缺陷:假設進程A此刻讀鎖變量為0,不巧的是來不及修改鎖變量,切換到另一個進程B,進程B也發現了鎖變量為0,它即認為可以進入臨界區。此時就會導致兩個進程同時讀寫。
3.嚴格輪換法
這個方法只適用於兩個進程。假設有一個變量turn(稱為自旋鎖spin lock),它的值用來記錄何時輪到某個進程執行。當turn=0時A進程進入臨界區,=1時B進程進入臨界區。雖然這個方法避免了兩個進程同時進入臨界區,可是當A進程需要很多的cpu時間,那麽這就會一直阻塞B進程的執行,所以違反了規則3:臨界區外的運行的進程不得阻塞其他進程。如下圖:
4.Peterson 解法
避免了嚴格輪換,如下圖:
//TODO
2.3 進程間通信