python的文件鎖目前使用的是fcntl這個庫,它實際上為 Unix上的ioctl
,flock和fcntl
函數提供了一個接口。
1.fcntl庫的簡單使用
import fcntl import os, time FILE = "counter.txt" if not os.path.exists(FILE): # create the counter file if it doesn't exist file = open(FILE, "w") file.write("0") file.close() for i in range(20): file = open(FILE, "r+") #由於flock生成的是勸告鎖,不能阻止進程對文件的操作,所以這里可以正常打開文件 fcntl.flock(file.fileno(), fcntl.LOCK_EX) #為了避免同時操作文件,需要程序自己來檢查該文件是否已經被加鎖。這里如果檢查到加鎖了,進程會被阻塞 print 'acquire lock' counter = int(file.readline()) + 1 file.seek(0) file.write(str(counter)) print os.getpid(), "=>", counter time.sleep(10) file.close() # unlocks the file print 'release lock' time.sleep(3)
分別啟動2個進程來同時運行這個腳本,我們可以很明顯的看到2者互相之間交替阻塞。同一時刻只有一個進程能夠對counter.txt文件進行操作。
2.對fcntl.flock()函數的說明:
linux的flock() 的函數原型如下所示:
int flock(int fd, int operation);其中,參數 fd 表示文件描述符;參數 operation 指定要進行的鎖操作,該參數的取值有如下幾種:
LOCK_SH:表示要創建一個共享鎖,在任意時間內,一個文件的共享鎖可以被多個進程擁有;
LOCK_EX:表示創建一個排他鎖,在任意時間內,一個文件的排他鎖只能被一個進程擁有;
LOCK_UN:表示刪除該進程創建的鎖;
LOCK_MAND:它主要是用於共享模式強制鎖,它可以與 LOCK_READ 或者 LOCK_WRITE聯合起來使用,從而表示是否允許並發的讀操作或者並發的寫操作;
通常情況下,如果加鎖請求不能被立即滿足,那么系統調用 flock()會阻塞當前進程。比如,進程想要請求一個排他鎖,但此時,已經由其他進程獲取了這個鎖,那么該進程將會被阻塞。如果想要在沒有獲得這個排他鎖的情況下不阻塞該進程,可以將LOCK_NB 和 LOCK_SH 或者 LOCK_EX 聯合使用,那么系統就不會阻塞該進程。flock()所加的鎖會對整個文件起作用。
注意:
1. 對於文件的 close() 操作會使文件鎖失效;
2. 同理,進程結束后文件鎖失效;
3. flock() 的 LOCK_EX是“勸告鎖”,系統內核不會強制檢查鎖的狀態,需要在代碼中進行文件操作的地方顯式檢查才能生效。
3.相關資料
1.Linux中的文件鎖的概念及其實現(http://blog.csdn.net/jianhong1990/article/details/26369465)
2.fcntl模塊的官方文檔(https://docs.python.org/2/library/fcntl.html#fcntl.flock)