flock FILEHANDLE,OPERATION

在 FILEHANDLE 上呼叫 flock(2) 或其模擬。成功傳回 true,失敗傳回 false。如果在未實作 flock(2)fcntl(2) 鎖定或 lockf(3) 的機器上使用,會產生致命錯誤。 flock 是 Perl 的可攜式檔案鎖定介面,儘管它只鎖定整個檔案,而不鎖定記錄。

兩個可能不顯而易見但傳統的 flock 語意是它會無限期等待直到鎖定被授予,而且它的鎖定僅供建議。這種自由裁量鎖定較為靈活,但提供的保證較少。這表示未同時使用 flock 的程式可能會修改使用 flock 鎖定的檔案。請參閱 perlport、您特定埠的說明文件,以及您系統特定的本機手冊頁面以取得詳細資料。如果您撰寫可攜式程式,最好假設傳統行為。(但如果您沒有,您應該像往常一樣完全自由地針對您自己的系統的特殊性(有時稱為「功能」)撰寫。對可攜性考量的奴性遵守不應妨礙您完成工作。)

OPERATION 是 LOCK_SH、LOCK_EX 或 LOCK_UN 之一,可能與 LOCK_NB 結合。這些常數傳統上分別為 1、2、8 和 4,但如果從 Fcntl 模組匯入,則可以使用符號名稱,個別匯入或使用 :flock 標籤作為群組匯入。LOCK_SH 要求共用鎖,LOCK_EX 要求獨佔鎖,而 LOCK_UN 釋放先前要求的鎖。如果 LOCK_NB 與 LOCK_SH 或 LOCK_EX 進行位元運算,則 flock 會立即傳回,而不是封鎖等待鎖定;檢查傳回狀態以查看是否取得鎖定。

為了避免失調的可能性,Perl 現在會在鎖定或解鎖 FILEHANDLE 之前先清除它。

請注意,使用 lockf(3) 建立的模擬不會提供共用鎖,而且要求 FILEHANDLE 以寫入意圖開啟。這些是 lockf(3) 實作的語意。大多數(如果不是全部)系統都使用 fcntl(2) 鎖定來實作 lockf(3),因此不同的語意不應該會影響太多人。

請注意,fcntl(2)flock(3) 的模擬要求 FILEHANDLE 以讀取意圖開啟才能使用 LOCK_SH,並要求以寫入意圖開啟才能使用 LOCK_EX。

另請注意,某些版本的 flock 無法鎖定網路上的項目;您需要使用更特定於系統的 fcntl 來執行此動作。如果您願意,可以強制 Perl 忽略系統的 flock(2) 函式,並提供它自己的 fcntl(2) 為基礎的模擬,方法是在設定和建置新的 Perl 時,將開關 -Ud_flock 傳遞給 Configure 程式。

以下是 BSD 系統的郵件匣附加程式。

# import LOCK_* and SEEK_END constants
use Fcntl qw(:flock SEEK_END);

sub lock {
    my ($fh) = @_;
    flock($fh, LOCK_EX) or die "Cannot lock mailbox - $!\n";
    # and, in case we're running on a very old UNIX
    # variant without the modern O_APPEND semantics...
    seek($fh, 0, SEEK_END) or die "Cannot seek - $!\n";
}

sub unlock {
    my ($fh) = @_;
    flock($fh, LOCK_UN) or die "Cannot unlock mailbox - $!\n";
}

open(my $mbox, ">>", "/usr/spool/mail/$ENV{'USER'}")
    or die "Can't open mailbox: $!";

lock($mbox);
print $mbox $msg,"\n\n";
unlock($mbox);

在支援真正的 flock(2) 的系統上,鎖會在 fork 呼叫中繼承,而必須使用較任性的 fcntl(2) 函式的鎖則會遺失,這讓撰寫伺服器變得更困難。

另請參閱 DB_File 以取得其他 flock 範例。

移植性問題:perlport 中的「flock」