fcntl有強大的功能,它能夠復制一個現有的描述符,獲得/設置文件描述符標記,獲得/設置文件狀態標記,獲得/設置異步I/O所有權,獲得/設置紀錄鎖。
當多個用戶共同使用,操作一個文件的情況,Linux通常采用的方法就是給文件上鎖,來避免共享資源產生競爭的狀態。
fcntl文件鎖有兩種類型:建議性鎖和強制性鎖
• 建議性鎖是這樣規定的:每個使用上鎖文件的進程都要檢查是否有鎖存在,當然還得尊重已有的鎖。內核和系統總體上都堅持不使用建議性鎖,它們依靠程序員遵守這個規定。(Linux默認是采用建議性鎖)
• 強制性鎖是由內核執行的。當文件被上鎖來進行寫入操作時,在鎖定該文件的進程釋放該鎖之前,內核會阻止任何對該文件的讀或寫訪問,每次讀或寫訪問都得檢查鎖是否存在。
使用fcntl文件鎖進行I/O操作必須小心:進程在開始任何I/O操作前如何去處理鎖,在對文件解鎖前如何完成所有的操作,是必須考慮的。如果在設置鎖之前打開文件,或者讀取該鎖之後關閉文件,另一個進程就可能在上鎖/解鎖操作和打開/關閉操作之間的幾分之一秒內訪問該文件。當一個進程對文件加鎖後,無論它是否釋放所加的鎖,只要文件關閉,內核都會自動釋放加在文件上的建議性鎖(這也是建議性鎖和強制性鎖的最大區別), 所以不要想設置建議性鎖來達到永久不讓別的進程訪問文件的目的(強制性鎖才可以)^_^;強制性鎖則對所有進程起作用。
在Linux中實現上鎖的函數有lock()和fcntl()。
• lock()用於對文件施加建議性鎖
• fcntl()用於對文件施加建議性鎖和強制性鎖都行。同時還可以對文件某一條紀錄進行上鎖,也就是記錄鎖。
例子:
• 例1,我有幾個進程(不一定有親緣關系)都通過fctnl機制來操作文件,這個就叫一致的方法。參見[2]
但是,如果同時,又有個流氓進程,管它3721,沖上去,open, write。
這時候那幾個進程fcntl對這種方式無能為力,這樣就叫不一致。文件最後的狀態就不定了。
正因為這種鎖約束不了其它的訪問方式,所以叫建議行鎖。強制性鎖需要內核支持的,對read, write, open都會檢查鎖。
• 例2,所謂建議性鎖就是假定人們都會遵守某些規則去干一件事。例如,人與車看到紅燈都會停,而看到綠燈才會繼續走,我們可以稱紅綠等為建議鎖。但這只是一種規則而已,你並不防止某些人強闖紅燈。而強制性鎖是你想闖紅燈也闖不了。參見[3]
如何在Linux系統上使用強制性鎖呢?
要想讓linux支持強制性鎖,不但在mount的時候需要加上-o mand(APUE中文版有誤,它寫成了_omand), 而且對要加鎖的文件也需要設置相關權限 (turn on set-group-ID and turn off group-execute)參見[4].