Linux flock 函式 檔案鎖

2021-10-14 21:01:41 字數 4500 閱讀 6913

檔案鎖是一種檔案讀寫機制,在任何特定的時間只允許乙個程序訪問乙個檔案。利用這種機制能夠使讀寫單個檔案的過程變得更安全。這裡我們使用flock()函式。

flock函式說明:flock()會依引數operation所指定的方式對引數fd所指的檔案做各種鎖定或解除鎖定的動作。此函式只能鎖定整個檔案,無法鎖定檔案的某一區域。

標頭檔案 #include

引數 operation有下列四種情況:

lock_sh 建立共享鎖定。多個程序可同時對同乙個檔案作共享鎖定。

lock_ex 建立互斥鎖定。乙個檔案同時只有乙個互斥鎖定。

lock_un 解除檔案鎖定狀態。

lock_nb 無法建立鎖定時,此操作可不被阻斷,馬上返回程序。通常與lock_sh或lock_ex 做or(|)組合。

單一檔案無法同時建立共享鎖定和互斥鎖定,而當使用dup()或fork()時檔案描述詞不會繼承此種鎖定。

返回值 返回0表示成功,若有錯誤則返回-1,錯誤**存於errno。

flock只要在開啟檔案後,需要對檔案讀寫之前flock一下就可以了,用完之後再flock一下,前面加鎖,後面解鎖。

程序使用flock嘗試鎖檔案時,如果檔案已經被其他程序鎖住,程序會被阻塞直到鎖被釋放掉,或者在呼叫flock的時候,採用lock_nb引數,在嘗試鎖住該檔案的時候,發現已經被其他服務鎖住,會返回錯誤。

flock鎖的釋放非常具有特色,即可呼叫lock_un引數來釋放檔案鎖,也可以通過關閉fd的方式來釋放檔案鎖(flock的第乙個引數是fd),意味著flock會隨著程序的關閉而被自動釋放掉

當使用lock_ex 排他鎖時,同一時刻只能有乙個程序鎖定成功,其餘進行只能阻塞,這種行為與多執行緒讀寫鎖中的寫鎖類似。

//lock

if ((lock_fd = open(lock_path, o_creat|o_wronly, 0664)) < 0)

if (flock(lock_fd, lock_ex) < 0)

//unlock

close(lock_fd);

這三個函式的作用都是給檔案加鎖,那它們有什麼區別呢?

首先flock和fcntl是系統呼叫,而lockf是庫函式。lockf實際上是fcntl的封裝,所以lockf和fcntl的底層實現是一樣的,對檔案加鎖的效果也是一樣的。後面分析不同點時大多數情況是將fcntl和lockf放在一起的。

關於flock函式,首先要知道flock函式只能對整個檔案上鎖,而不能對檔案的某一部分上鎖,這是於fcntl/lockf的第乙個重要區別,後者可以對檔案的某個區域上鎖。

其次,flock只能產生勸告性鎖。我們知道,linux存在強制鎖(mandatory lock)和勸告鎖(advisory lock)。所謂強制鎖,比較好理解,就是你家大門上的那把鎖,最要命的是只有一把鑰匙,只有乙個程序可以操作。所謂勸告鎖,本質是一種協議,你訪問檔案前,先檢查鎖,這時候鎖才其作用,如果你不那麼kind,不管三七二十一,就要讀寫,那麼勸告鎖沒有任何的作用。而遵守協議,讀寫前先檢查鎖的那些程序,叫做合作程序。

再加上,flock可以有共享鎖和排它鎖,lockf只支援排它鎖,但是fcntl裡面引數flock可以有rdlck讀鎖。

再次,flock和fcntl/lockf的區別主要在fork和dup時候的區別,後面有講。

另外,flock不能再nfs檔案系統上使用,如果要在nfs使用檔案鎖,請使用fcntl。

l 函式原型

#include

int lockf(int fd, int cmd, off_t len);

fd為通過open返回的開啟檔案描述符。

cmd的取值為:

f_lock:給檔案互斥加鎖,若檔案以被加鎖,則會一直阻塞到鎖被釋放。

f_tlock:同f_lock,但若檔案已被加鎖,不會阻塞,而回返回錯誤。

f_ulock:解鎖。

f_test:測試檔案是否被上鎖,若檔案沒被上鎖則返回0,否則返回-1。

len:為從檔案當前位置的起始要鎖住的長度。

通過函式引數的功能,可以看出lockf只支援排他鎖,不支援共享鎖。

#include

#include

int fcntl(int fd, int cmd, ... /* arg */ );(用法:int ret = fcntl(fd, f_setlkw, &lock);)

其實的lock就是下面的資料結構:

struct flock 測試結果如下:

$./a.out

flock return ret : 0

lockf return ret: 0

可見flock的加鎖,並不影響lockf的加鎖。兩外我們可以通過/proc/locks檢視程序獲取鎖的狀態。

$ps aux | grep a.out | grep -v grep

123751   18849  0.0  0.0  11904   440 pts/5    s+   01:09   0:00 ./a.out

$sudo cat /proc/locks | grep 18849

1: posix  advisory  write 18849 08:02:852674 0 eof

2: flock  advisory  write 18849 08:02:852674 0 eof

我們可以看到/proc/locks下面有鎖的資訊:我現在分別敘述下含義:

1) posix flock 這個比較明確,就是哪個型別的鎖。flock系統呼叫產生的是flock,fcntl呼叫f_setlk,f_setlkw或者lockf產生的是posix型別,可見兩種呼叫產生的鎖的型別是不同的;

2) advisory表明是勸告鎖;

3) write顧名思義,是寫鎖,還有讀鎖;

4) 18849是持有鎖的程序id。當然對於flock這種型別的鎖,會出現程序已經退出的狀況。

5) 08:02:852674表示的對應磁碟檔案的所在裝置的主裝置號,次裝置號,還有檔案對應的inode number。

6) 0表示的是所的其實位置

7) eof表示的是結束位置。 這兩個欄位對fcntl型別比較有用,對flock來是總是0 和eof。

fcntl支援強制性鎖:對乙個特定檔案開啟其設定組id位(s_isgid),並關閉其組執行位(s_ixgrp),則對該檔案開啟了強制性鎖機制。再linux中如果要使用強制性鎖,則要在檔案系統mount時,使用-omand開啟該機制。

#include #include int main(int argc, char **ar**) 

static struct flock lock;

lock.l_type = f_wrlck;

lock.l_start = 0;

lock.l_whence = seek_set;

lock.l_len = 0;

lock.l_pid = getpid();

int ret = fcntl(fd, f_setlkw, &lock);

printf("return value of fcntl:%d\n",ret);

if(ret==0)

}}}

使用mount命令帶「mand」引數來重新掛載根檔案系統,如下所示。這將在檔案系統級別使能強制鎖功能。注意:你必須切換到root使用者才能執行下面的命令。# mount -oremount,mand /

在可執行的(file_lock所在的)目錄中建立兩個名為「advisory.txt」和「mandatory.txt」的檔案。對於「mandatory.txt」使能set-group-id,同時不使能group-execute-bit,如下所示:

# touch advisory.txt

# touch mandatory.txt

# chmod g+s,g-x mandatory.txt

測試協同鎖:

執行示例程式,以「advisory.txt」作為引數。

# ./file_lock advisory.txt

此程式將等待使用者的輸入。從另乙個終端或控制台,嘗試輸入以下命令列(不檢查鎖,直接輸入):

# ls >>advisory.txt

在上面的例子中,ls命令會將其輸出寫入到advisory.txt檔案中。即使我們獲得了乙個寫入鎖,仍然會有一些程序(非合作)能夠往檔案裡寫入資料。這就是所謂的「協同」鎖。

測試強制鎖:

再次執行示例程式,以「mandatory.txt」作為引數。

# ./file_lock mandatory.txt

從另乙個終端或控制台,嘗試輸入以下命令列:

# ls >>mandatory.txt

在上面的例子中,ls命令在將其輸出寫入到mandatory.txt檔案之前,會等待檔案鎖被刪除。雖然它仍然是乙個非合作程序,但強制鎖起了作用。

Linux flock檔案鎖詳解

摘要1 摘要2 摘要3 用flock命令解決linux計畫任務重複執行 在做計畫任務的時候,可能由於某些問題,任務沒有執行完成,導致任務重複的執行,解決這個問題,只需要乙個flock命令就可以了。1.建立s 件 vim test.sh bin bash echo hello world sleep ...

flock 函式 檔案鎖

檔案鎖是一種檔案讀寫機制,在任何特定的時間只允許乙個程序訪問乙個檔案。利用這種機制能夠使讀寫單個檔案的過程變得更安全。這裡我們使用flock 函式。flock函式說明 flock 會依引數operation所指定的方式對引數fd所指的檔案做各種鎖定或解除鎖定的動作。此函式只能鎖定整個檔案,無法鎖定檔...

php中檔案鎖函式flock函式用法簡介

php中檔案鎖函式flock函式用法簡介 語法 bool flock int handle int operation int wouldblock flock 操作的 handle 必須是乙個已經開啟的檔案指標。operation 可以是以下值之一 1.要取得共享鎖定 讀取程式 將 operati...