來源:互聯網
上載者:User
關鍵字
linux
read-write-lock
php
首先鎖資訊是不是檔案的一部分?
其次斷電重啟後會自動消失還是永遠存在無法解除(因為設定鎖的進程已經不複存在了)?
回複內容:
首先鎖資訊是不是檔案的一部分?
其次斷電重啟後會自動消失還是永遠存在無法解除(因為設定鎖的進程已經不複存在了)?
Linux下的檔案鎖
Linux下有兩種不同的檔案鎖機制,一種是通過 flock
系統調用鎖定整個檔案,另一種是通過 fcntl
系統調用完成更細粒度的記錄鎖(鎖定檔案中的一個區間)
open 系統調用
Linux下,在最初開啟一個檔案的時候,最終都是落到 open
這個系統調用上。
open系統調用 (@./fs/open.c) 裡頭做了很多事情,跟檔案鎖有關的主要是分配了一個 struct file
對象,並且給該對象的 struct inode *inode
和 struct file_operations *f_op
成員賦值。
其中 inode 是對應檔案系統分配的(比如 ext4 檔案系統的分配函數是 fs/ext4/inode.c 中的 ext4_iget
),其中也包含了一個 struct file_operations *
類型的成員 i_fop
,即針對該檔案系統檔案操作的函數指標集合。
以上提到的兩次 struct file_operations
對象包含 flock
和 lock
兩個函數指標,分別用於上述的兩種不同鎖機制。
核心在記憶體中只會給一個檔案分配一個 struct inode
對象,不同進程開啟同一個檔案時,都會單獨分配一個 struct file
對象,且 file->inode
指向該檔案對應的 inode 對象。其中 file->f_op
實際上就是在 open 系統調用過程中,從 inode->i_fop
拷貝過來的。(open -> do_sys_open -> do_filp_open -> path_openat -> do_last -> vfs_open -> do_dentry_open: f->f_op = fops_get(inode->i_fop)
)
flock 加鎖
核心首先根據第一個參數 fd 找到核心中的 struct file
對象,判斷 file->f_op->flock
指標是否有效,如果有效(說明是檔案系統指定了加鎖機制,例如 fs/fuse/file.c 中指定了 fuse_file_flock
函數,而ext2/3/4都沒有指定),就調用該指標指向的函數來執行加鎖操作;如果不存在,則執行flock_lock_file_wait
-> flock_lock_inode
(@ fs/locks.c)。
如果檔案系統沒有指定加鎖機制,那麼 flock_lock_inode
會嘗試給該檔案對應的 inode 加檔案鎖(加鎖機制比較瑣碎,我沒看得太細,大致是擷取 inode->i_flctx->flc_lock
這個spinlock,然後增刪改查 inode->i_flctx->flc_flock
這個鏈表,但是可以看出全是記憶體操作)。
如果檔案系統指定了加鎖機制,那麼就要具體考察對應的加鎖機制是否是持久化在磁碟上了;不過從加鎖這個需求本身去考察,大多數情況下應當是期望能夠快速完成,除了特殊情況,可以認為只是在記憶體中操作,並沒有持久化到磁碟。
fcntl 加鎖
與 flock
類似,區別在於判斷的函數指標是 file->f_op->lock
,如果不存在的話,則調用 posix_lock_file
嘗試對該 inode 加記錄鎖,也是在 inode->i_flctx
上面倒騰,不過用的是 inode->i_flctx->flc_lock
這個鏈表,具體操作更複雜一些,還要考慮記錄鎖區間的交叉等問題。
結論
具體情況取決於檔案系統是否使用了指定的加鎖機制,如果有,要單獨分析。
如果沒有,所有的鎖都是在記憶體中維護的,如果斷電,鎖自動失效。這樣也比較符合通常的理解。
另外,針對檔案的加鎖行為一般都是進程執行的,進程退出(包括意外退出)時,exit 系統調用會調用 exit_files
函數清理該進程開啟的所有檔案。