[fcntl][NFS][MacOS] 鎖文件 IOError: [Errno 35] Resource temporarily unavailable


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()))
  1. 保持以上terminal 不中斷,開第二個terminal,運行同樣代碼,執行到lockf時,無任何輸出

  2. 重新來,在lockf那一段加入一個參數 fcntl.LOCK_NB

fcntl.lockf(f, fcntl.LOCK_SH | fcntl.LOCK_NB)

  1. 重新執行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
  1. 所以,一般寫操作,需要鎖定文件,用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))
     
  1. 解鎖用:fcntl.LOCK_UN , f.close()也能解鎖。

另外學到個新用法 os.fstat(f.fileno()) 可以輸出文件的uid,gid,device等信息;

(Pdb) os.fstat(fildes.fileno())
posix.stat_result(st_mode=33216, st_ino=4297196284, st_dev=872415337, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1587695736, st_mtime=1587695736, st_ctime=1587695736)

此段代碼在smb mount point上執行,報錯如下,應該是lockf不支持smb,但是還能不能繼續用fcntl了呢?
IOError: (45, 'Operation not supported')

補充:

enum nfs_lock_type4 {
           READ_LT         = 1,
           WRITE_LT        = 2,
           READW_LT        = 3,    /* blocking read */
           WRITEW_LT       = 4     /* blocking write */
   };

nfs.opcode == 12 ----> create lock
nfs.opcode == 14 ----> unlock file


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM