1. 程式人生 > >Unix系統編程()原子操作和競爭條件

Unix系統編程()原子操作和競爭條件

例子 one cpu order https alt left 發生 see

競爭狀態是這樣一種情形:操作共享資源的兩個進程(或線程),其結果取決於一個無法預期的順序,即這些進程獲得CPU使用權的先後相對順序。

以獨占的方式創建一個文件

當同時指定了O_EXCL和O_CREAT作為open的標誌位時,如果要打開的文件已經存在,則open將返回一個錯誤。

這種機制為了保證進程是打開文件的創建者。

對文件是否存在的檢查和創建屬於同一原子操作。、

如果不實用O_EXCL標誌的話,要調用兩次open,以此判斷文件是否存在,一個是創建一個文件。

但有個情況是:

當第一次調用open時,希望打開的文件還不存在,而當第二次調用open時,其他進程已經創建了該文件。

如下圖,若內核調度器判斷出分配給A進程的時間片已經耗盡,並且將CPU的使用權交給B進程,就有肯能發生這種問題。

再比如兩個進程在一個多CPU系統上同時運行,也會出現這種情況。

在這種情況下,A會認為目標文件是由自己創建的。因為不論目標文件存在與否,進程A對open的第二次調用都會成功。

技術分享圖片

由於第一個進程在檢查文件是否存在和創建文件之間發生了中斷,造成兩個進程都聲稱自己是文件的創建者。

結合O_CREAT和O_EXCL標誌來一次性地調用open可以防止這種情況,因為這確保了檢查和創建文件的捕捉屬於一個單一的原子(不可中斷的)操作。

向文件尾部追加數據

說明原子操作的第二個例子是:多個進程文件同時同一個文件(例如,全局日誌文件)尾部添加數據。

每次寫入新的日誌時,會用lseek將文件偏移量設置到文件尾部,然後再寫入數據。

但是在lseek和write之間會被其他進程所打斷,那麽這兩個進程在寫入數據前,將文件偏移量設為相同位置,而當第一個進程再次獲得調度時,會覆蓋第二個進程已寫入的數據。此時再次出現了競爭狀態,因為執行的結果依賴於內核對兩個進程的調度順序。

要規避這一個問題,需要將文件偏移量的移動與數據寫入操作納入同一個原子操作。在打開文件時加入O_APPEND標誌就可以保證這一點。

註意了,在打開文件時加入O_APPEND標誌。所以這個意思就是,打開之後的寫都是先移到文件末尾,在寫數據咯?

Unix系統編程()原子操作和競爭條件