最近由於在我們的檔案系統中需要實現posix檔案鎖,因此研究了下linux核心和gluster的檔案鎖的實現的**。主要關注posix檔案鎖。整理了相關的學習內容,概念方面主要摘自網路和將系統核心的兩本書(《linux核心深入理解》和《核心情景分析》)。**部分參考了書的描述,然後閱讀了相關**。
主要參考**,請搜尋《linux 2.6 中的檔案鎖》
按讀寫特性:共享鎖(讀鎖)和排它鎖(寫鎖)
按鎖的工作方式:強制鎖、勸告鎖、共享模式鎖、租借鎖
核心只提供加鎖以及檢測檔案是否已經加鎖的方法,但不參與鎖的控制和協調。如果有程序不遵守「遊戲規則」,不檢查目標檔案是否已經由別的程序加了鎖就往其中寫入資料,那麼核心是不會阻攔的。
當有系統呼叫
open()
、read()
以及write()
發生的時候,核心都要檢查並確保這些系統呼叫不會違反在所訪問檔案上加的強制鎖約束。
unlink
不會受到強制鎖的影響。
當程序對檔案進行了讀或寫這樣的系統呼叫時,系統則會檢查該檔案已經到加強製鎖時,會判斷檔案的狀態
o_nonblock
標識,如果設定了
o_nonblock
,則該程序會出錯
eagain
返回;否則,該程序被阻塞
標識設定方式是通過
fcntl
傳遞引數
f_setfl。
系統支援強制鎖的配置:
mount –o mand
設定檔案系統是否支援強制鎖(
super_block
結構中s_flags
設定為0或1
) 修改要加強製鎖的檔案的許可權:設定
sgid
位,並清除組可執行位。
程序對某個檔案擁有的各種鎖會在檔案對應的檔案描述符被關閉時自動清除;
程序執行結束後,其所加的各種鎖也會自動清除。
由fork
產生的子程序不會繼承父程序的檔案鎖;
在執行exec
之後,新程式可以繼承原來程式的檔案鎖。
系統中所有檔案的活動的鎖都鏈結在乙個全域性的單向鍊錶
file_lock_list
中,inode->i_flock
blocked_list
中。file_lock_lock
保護這兩個鍊錶。
file_lock
,linux
核心描述的所有型別鎖的資料結構
poxis
檔案鎖通過
fcntl
系統呼叫實現:
int fcntl (int fd, intcmd, struct flock *lock);
struct flock ;
f_getlk/ f_setlk/ f_setlkw
f_getlk
:獲取相應型別的鎖,如果存在,返回相應鎖的資訊(包括
l_pid
設定為加鎖程序的
pid)
;如果不存在,
l_type
被賦值為
f_unlck
; fcntl_getlk
2. f_setlk
:設定鎖(
l_type
為f_rdlck, f_wrlck
或f_unlck
),如果檔案已經到其它鎖鎖定,直接返回
eagain;
f_setlkw
:設定鎖,如果檔案已經到其它鎖鎖定,阻塞,進入睡眠;
fcntl_setlk
f_setlease
和f_getlease
可以實現租約鎖,具體引數(
f_rdlck
、f_wrlck
、f_unlck)
某個程序可能會對檔案執行其他一些系統呼叫(比如
open()
或者truncate()
),如果這些系統呼叫與該檔案上由
f_setlease
所設定的租借鎖相衝突,核心就會阻塞這個系統呼叫;同時,核心會給擁有這個租借鎖的程序發訊號。擁有此租借鎖的程序會對該訊號進行處理,可能會刪除或縮短這個租借鎖。
如果擁有租借鎖的程序不能在給定時間內完成上述操作,那麼系統會強制完成。通過
f_setlease
命令將arg
引數指定為
f_unlck
就可以刪除這個租借鎖。
即使被阻塞的系統呼叫因為某些原因被解除阻塞,但是對租借鎖的租約進行減短或刪除這個過程還是會執行的。
租借鎖也只能對整個檔案生效,而無法實現記錄級的加鎖。
open_namei()
如果open
的標誌包括
trunc
,會通過
locks_mandatory_locked
檔案是否加了
poxis
鎖,mandatory_lock
判斷檔案是否支援強制鎖,然後遍歷所有鎖,比較其中強制鎖的
owner
是否是當前,如果不是,返回錯誤
eagain
filp_close()
呼叫locks_remove_posix
owner
is the posix threadid. we use the files pointer for this.(files_struct)
locks_mandatory_area
fl.fl_flags= fl_posix | fl_access;
if (filp && !(filp->f_flags & o_nonblock))
fl.fl_flags|= fl_sleep;
fl.fl_type= (read_write == flock_verify_write) ? f_wrlck : f_rdlck;
注意:沒有呼叫
vfs_lock_file.
file_lock_lock加鎖
遍歷所有的
lock
,如果fl_type
不是f_unlck
,檢查是否產生衝突,如果是,判斷
fl_flags
是否設定
fl_sleep
(返回-eagain
),是否死鎖(
-edeadlk
),locks_insert_block
插入等待列表。
locks_insert_block:
3.如果
request->fl_flags & fl_access
,退出 4.從
inode
上找到相同的
own的的第乙個鎖,然後如果是相同型別的鎖,判斷是否進行合併;如果是不同型別的鎖,交叉部分,新鎖總是覆蓋舊鎖的型別(舊鎖的部分要
wake_up
上面阻塞的鎖),然後舊鎖可能產生拆分。
5. 由於合併或覆蓋或
f_unlck
等原因需要呼叫
locks_delete_lock
釋放鎖。
locks_delete_lock:
6. 把可能產生的拆分和新的
file_lock
插入(locks_insert_lock
)全域性鎖鏈表和索引節點鍊錶中
locks_insert_lock:
7. file_lock_lock解鎖
Linux 核心自旋鎖
現在很多cpu都是幾核幾核的了,如果有乙個變數a,cpu x正在訪問,突然cpu y也過來訪問他,這時候就可能出現問題,因為這個a非常重要,可能導致系統崩潰,中斷異常等。我們來看之前說的tp驅動裡面的 void gtp irq enable struct goodix ts data ts spin...
linux核心鎖機制
核心鎖的討論 為什麼需要核心鎖?多核處理器下,會存在多個程序處於核心態的情況,而在核心態下,程序是可以訪問所有核心資料的,因此要對共享資料進行保護,即互斥處理 有哪些核心鎖機制?1 原子操作 atomic t資料型別,atomic inc atomic t v 將v加1 原子操作比普通操作效率要低,...
Linux核心無鎖程式設計
多核多執行緒已經成為當下乙個時髦的話題,而無鎖程式設計更是這個時髦話題中的熱點話題。linux核心可能是當今最大最複雜的並行程式之一,為我們分析多核多執行緒提供了絕佳的範例。核心設計者已經將最新的無鎖程式設計技術帶進了2。6系統核心中,本文以2。6。10版本為藍本,帶領您領略多核多執行緒程式設計的真...