O_EXCL
open系統調用:
#include <fcntl.h>int open(const char *pathname, int oflag, ... /*mode_t mode */ );其中,oflag有個可選值為:
O_EXCL
Generate an error if?O_CREAT?is also specified and the file already exists.?
This test for whether the file already exists and the creation of the file if it doesn't exist is an atomic operation.?
We describe atomic operations in more detail in Section 3.11.
譯文:當 O_CREAT 與 O_EXCL 同時使用,并且如果要打開的文件已經存在,那么該調用就返回error,表明打開不成功。因此,我們可以使用該方法(即 O_CREAT 與 O_EXCL 同時使用)來實現以下三步的原子性操作:1 檢查某個文件是否存在2 如果文件不存在,就創建該文件,返回 success3 如果文件已經存在,就返回error,通知調用者文件已經存在---------------------------------------------華麗麗的分割線-----------------------------------以下是從網上找的一些信息:$ man open......
? O_EXCL Ensure that this call creates the file: if this flag is specified in conjunc-
? tion with O_CREAT, and pathname already exists, then open() will fail.?The
behavior of O_EXCL is undefined if O_CREAT is not specified.=============================================================================================設想這樣一個需求:某個任務要求只能單個進程執行,不能多個進程同時執行。
但是不能確保多個進程同時啟動,嘗試執行這個任務。
這樣就進一步要求,只有第一個執行的進程可以繼續,后續嘗試執行的進程都報錯退出。
方案之一就是使用帶有O_EXCL標志的open()嘗試打開一個文件。
第一個進程執行時文件并不存在,它能成功創建文件并繼續執行。
第二個及后續的其它進程會因為文件已存在,從而open()失敗,進程退出。
如果不使用O_EXCL標志,那你的代碼可能要這樣寫:
if( access(file, R_OK) == -1 ) /* 首先檢查文件是否存在 */
? open(file, O_RDWR | O_CREAT,0666); /* 如果不存在,那我創建一個這樣的文件 */
... /* 繼續執行任務 */
這個邏輯是有潛在的問題的,那就是判斷文件是否存在與創建文件是兩個獨立的系統調用。
如果進程1執行access,判斷出文件并不存在;
然后由于操作系統的調度策略,進程1暫停執行,進程2執行,進程2也會判斷出文件不存在。
最終結果就是:兩個進程調用open時都會成功,然后繼續執行。這樣就有多個進程同時執行這個任務了。---------------------------------------------------------------------------------------------------總結下 (O_EXCL|O_CREAT)與 O_CREAT 的區別:1 單獨使用 O_CREAT 時,無論文件在該調用執行時,是否存在,都會成功返回(不考慮所在目錄權限、文件權限的問題)。如果應用程序只要求確保文件在后續程序執行時,該文件已經存在,則單獨使用 O_CREAT 就可滿足該應用要求。但有一個不足之處就是:當open成功返回后,我們需要知道該文件是之前已經存在呢,還是之前不存在而剛剛創建出來的。如果有這種需求,那么 單獨使用 O_CREAT 就不能搞定了。此時,就需要使用(O_EXCL|O_CREAT)。2 當使用(O_EXCL|O_CREAT)時,若文件已存在,則返回錯誤;過不存在,則返回成功。但返回不論成功、錯誤,返回后,文件肯定已經存在了。因此,該方式能夠給程序員提供更多的信息量。
區別應該就在這里吧。
那么在apue中,在介紹?Ensure that only one copy of a daemon is running中,作者并沒有使用(O_EXCL|O_CREAT)來通過判斷某個文件是否存在來判斷是否有某個進程的其它實例正在運行。而是采用了O_CREAT,而后加“寫鎖”的方式。
想想這兩種方式的特點:
如果采用?(O_EXCL|O_CREAT)來實現單實例進程,那么進程結束之前,必須要先刪除鎖文件,否則,以后該程序就無法運行了。因此問題就在如何保證刪除鎖文件。比如突然斷電,程序還沒來得及刪除鎖文件,那么下次再無法運行了。處理好這個問題需要額外畫一些功夫。
apue中采用的采用 record lock 的方式,應該是不存在上面提到的這種問題。
總結
- 上一篇: SIP应答消息状态码与功能
- 下一篇: 上海期货交易所怎么开户?要多少钱?