lockf 是 fcntl的封装,底层实现一样
flock: lock the whole file,只能对整个文件上锁,支持建议锁,共享锁,排他锁, 不能用在nfs上
fcntl(可用在nfs上), lockf: 整个文件 或者 文件部分字节的锁, 只支持排他锁
共享锁必须是读打开,排他锁必须是写打开
排他锁:写锁, 独占锁, 同一时间只有一个进程可以加
fcntl.LOCK_SH '共享锁'
fcntl.LOCK_EX '排他锁'
fcntl.LOCK_NB '非阻塞锁——如果指定此参数,函数不能获得文件锁就立即返回,否则,函数会等待获得文件锁。LOCK_NB可以同LOCK_SH或LOCK_NB进行按位或(|)运算操作。 fcntl.flock (f,fcntl.LOCK_EX|fcntl.LOCK_NB)'
fcntl.LOCK_UN '解锁'
环境:
client: macos
protocol: nfsv4
目的:
强制锁定文件以做写操作
实现方式:
fcntl.lockf(f, fcntl.LOCK_SH | fcntl.LOCK_NB)
验证是否锁成功:
1.在terminal 1中:
import fcntl
path = '/var/root/dev/1.txt'
f = open(path, 'wb')
fcntl.lockf(f, fcntl.LOCK_SH)
print('getpid:{0}'.format(os.getpid()))
-
保持以上terminal 不中断,开第二个terminal,运行同样代码,执行到lockf时,无任何输出
-
重新来,在lockf那一段加入一个参数
fcntl.LOCK_NB
fcntl.lockf(f, fcntl.LOCK_SH | fcntl.LOCK_NB)
- 重新执行step1 和 step2, 到第二个fcntl.lockf时,得到如下error messgae,说明锁成功:
>>> f = open(path, 'wb')
>>> fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 35] Resource temporarily unavailable
>>> fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 35] Resource temporarily unavailable
- 所以,一般写操作,需要锁定文件,用try/except 来捕获IOError:
把以上代码补完整:
import fcntl
path = '/var/root/dev/1.txt'
try:
with open(path, 'wb') as f:
fcntl.lockf(f, fcntl.LOCK_SH)
print('getpid:{0}'.format(os.getpid()))
except IOError as e:
print("Another instance is already running {0}".format(e))
另外学到个新用法 os.fstat(f.fileno()) 可以输出文件的uid,gid,device等信息;
此段代码在smb mount point上执行,报错如下,应该是lockf不支持smb,但是还能不能继续用fcntl了呢?
IOError: (45, 'Operation not supported')