#!/usr/bin/python # coding:utf8 import os import sys import time import fcntl # 導入模塊 class FLOCK(object): def __init__(self, name): """ :param name: 文件名 """ self.fobj = open(name, 'w') self.fd = self.fobj.fileno() def lock(self): try: fcntl.lockf(self.fd, fcntl.LOCK_EX | fcntl. LOCK_NB) # LOCK_NB: 使用了fcntl.LOCK_NB,已有進程對該文件已加鎖,本進程得不到鎖時直接退出,不阻塞。若是不加非阻塞參數,得不到鎖就卡在這裏一直傻等着直到拿到鎖 print('給文件加鎖,稍等 ... ...') time.sleep(20) return True except Exception as e : print('文件加鎖,沒法執行,請稍後運行。\n',e) return False def unlock(self): self.fobj.close() print('已解鎖') if __name__ == "__main__": locker = FLOCK(sys.argv[1]) a = locker.lock() if a: print('文件已加鎖') else: print('沒法執行,程序已鎖定,請稍等')
fcntl.flock 和fcntl.lockf 的區別:http://blog.chinaunix.net/uid-28541347-id-5678998.htmlhtml
https://blog.csdn.net/mydriverc2/article/details/80263930python
lockf 子進程不會繼承主進程的鎖linux
flock 子進程繼承主進程的鎖,這個感受用的多些ide
#include 函數
int flock(int fd, int operation); // Apply or remove an advisory lock on the open file specified by fd,只是建議性鎖ui
其中fd是系統調用open返回的文件描述符,operation的選項有:spa
LOCK_SH :共享鎖.net
LOCK_EX :排他鎖或者獨佔鎖unix
LOCK_UN : 解鎖。code
LOCK_NB:非阻塞(與以上三種操做一塊兒使用)
關於flock函數,首先要知道flock函數只能對整個文件上鎖,而不能對文件的某一部分上鎖,這是於fcntl/lockf的第一個重要區別,後者能夠對文件的某個區域上鎖。其次,flock只能產生勸告性鎖。咱們知道,linux存在強制鎖(mandatory lock)和勸告鎖(advisory lock)。所謂強制鎖,比較好理解,就是你家大門上的那把鎖,最要命的是隻有一把鑰匙,只有一個進程能夠操做。所謂勸告鎖,本質是一種協議,你訪問文件前,先檢查鎖,這時候鎖才其做用,若是你不那麼kind,無論三七二十一,就要讀寫,那麼勸告鎖沒有任何的做用。而遵照協議,讀寫前先檢查鎖的那些進程,叫作合做進程。再次,flock和fcntl/lockf的區別主要在fork和dup。
(1) flock建立的鎖是和文件打開表項(struct file)相關聯的,而不是fd。這就意味着複製文件fd(經過fork或者dup)後,那麼經過這兩個fd均可以操做這把鎖(例如經過一個fd加鎖,經過另外一個fd能夠釋放鎖),也就是說子進程繼承父進程的鎖。可是上鎖過程當中關閉其中一個fd,鎖並不會釋放(由於file結構並無釋放),只有關閉全部複製出的fd,鎖纔會釋放。
#!/usr/bin/env python # -*- coding:utf8 -*- import os import sys import time import fcntl # 導入模塊 class FLOCK(object): def __init__(self, name): """ :param name: 文件名 """ self.fobj = open(name, 'w') self.fd = self.fobj.fileno() def lock(self): try: fcntl.flock(self.fd, fcntl.LOCK_EX |fcntl.LOCK_NB ) # LOCK_NB: 使用了fcntl.LOCK_NB,已有進程對該文件已加鎖,本進程得不到鎖時直接退出,不阻塞若是不加非阻塞參數,得不到鎖就卡在這裏> 一直等拿到鎖 print('已給文件加鎖, ... ...') fork_resu = os.fork() if fork_resu == 0: print('子進程睡眠中') time.sleep(20) print('子進程退出') else: sys.exit('主進程已退出') time.sleep(20) #return True except Exception as e : print('文件已加鎖,沒法執行,請稍後運行。\n',e) return False return False def unlock(self): self.fobj.close() print('已解鎖') if __name__ == "__main__": locker = FLOCK(sys.argv[1]) locker.lock()
''' 窗口1先運行 [root@vm192-168-3-2 fcn_study]# python locktest.py l.txt 已給文件加鎖, ... ... 主進程已退出 子進程睡眠中 (base) [root@vm192-168-3-2 fcn_study]# ''' '''窗口2後運行 [root@vm192-168-3-2 fcn_study]# python locktest.py l.txt 文件已加鎖,沒法執行,請稍後運行。 [Errno 11] Resource temporarily unavailable '''
若是代碼改成lockf 加鎖
'''窗口1 python locktest.py l.txt 已給文件加鎖, ... ... 主進程已退出 (base) [root@vm192-168-3-2 fcn_study]# 子進程睡眠中 ''' '''窗口2 root@vm192-168-3-2 fcn_study]# python locktest.py l.txt 已給文件加鎖, ... ... 主進程已退出 (base) [root@vm192-168-3-2 fcn_study]# 子進程睡眠中 ----窗口1和2 相互無影響 '''