在 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 之前会刷新 FILEHANDLE。
请注意,使用 lockf(3) 构建的仿真不提供共享锁,并且要求 FILEHANDLE 以写入意图打开。这些是 lockf(3) 实现的语义。尽管并非所有系统都实现 lockf(3),但大多数系统都是根据 fcntl(2) 锁定实现的,因此不同的语义不会影响太多人。
请注意,fcntl(2) 对 flock(3) 的仿真要求 FILEHANDLE 以读取意图打开才能使用 LOCK_SH,并且要求 FILEHANDLE 以写入意图打开才能使用 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) 函数的系统会丢失锁,这使得编写服务器变得非常困难。
可移植性问题:perlport 中的“flock”。