在Perl中创建文件锁的最佳方法是什么?
最好是聚集文件或创建锁定文件以锁定并检查锁定文件上的锁定?
如果你最终使用flock,这里有一些代码:
use Fcntl ':flock'; # Import LOCK_* constants # We will use this file path in error messages and function calls. # Don't type it out more than once in your code. Use a variable. my $file = '/path/to/some/file'; # Open the file for appending. Note the file path is quoted # in the error message. This helps debug situations where you # have a stray space at the start or end of the path. open(my $fh, '>>', $file) or die "Could not open '$file' - $!"; # Get exclusive lock (will block until it does) flock($fh, LOCK_EX) or die "Could not lock '$file' - $!"; # Do something with the file here... # Do NOT use flock() to unlock the file if you wrote to the # file in the "do something" section above. This could create # a race condition. The close() call below will unlock the # file for you, but only after writing any buffered data. # In a world of buffered i/o, some or all of your data may not # be written until close() completes. Always, always, ALWAYS # check the return value of close() if you wrote to the file! close($fh) or die "Could not write '$file' - $!";
一些有用的链接:
PerlMonks文件锁定教程(有点旧)
flock()
文件
为了回答您添加的问题,我要么说锁定在文件上,要么创建一个文件,当文件被锁定时你称之为'lock',当它不再被锁定时删除它(然后确保你的程序服从那些语义).
其他答案很好地涵盖了Perl flock,但在许多Unix/Linux系统上实际上有两个独立的锁定系统:BSD flock()和基于POSIX fcntl()的锁.
除非在构建Perl时提供配置的特殊选项,否则它的flock将使用flock()(如果可用).这通常很好,如果您只需要在应用程序中锁定(在单个系统上运行),可能就是您想要的.不过,有时你需要与使用的fcntl()锁(如sendmail,在许多系统上),或者你需要做的文件通过NFS安装的文件系统锁定另一个应用程序进行交互.
在这些情况下,您可能希望查看File :: FcntlLock或File :: lockf.也可以在纯Perl中执行基于fcntl()的锁定(带有一些有毛和非便携的pack()).
flock/fcntl/lockf差异的快速概述:
lockf几乎总是在fcntl之上实现,只有文件级锁定.如果使用fcntl实现,则以下限制也适用于lockf.
fcntl提供范围级锁定(在文件中)和NFS上的网络锁定,但fork()之后子进程不会继承锁.在许多系统上,您必须将文件句柄打开为只读以请求共享锁,并使用读写来请求独占锁.
flock只有文件级锁定,锁定只在一台机器内(你可以锁定一个NFS挂载的文件,但只有本地进程才会看到锁定).锁由子进程继承(假设文件描述符未关闭).
有时(SYSV系统)flock是使用lockf或fcntl模拟的; 在一些BSD系统上,使用flock模拟lockf.通常这些类型的仿真效果很差,建议您避免使用它们.
CPAN救援:IO :: LockedFile.
Ryan P写道:
在这种情况下,文件在重新打开文件时实际上会在短时间内解锁.
所以不要这样做.相反,open
读/写文件:
open my $fh, '+<', 'test.dat' or die "Couldn’t open test.dat: $!\n";
当您准备好编写计数器时,只需seek
返回文件的开头即可.请注意,如果您这样做,您应该truncate
在之前close
,以便如果文件的新内容比以前的内容短,则文件不会留下尾随垃圾.(通常,文件中的当前位置在最后,所以你可以写truncate $fh, tell $fh
.)
另外,请注意我使用了三个参数open
和一个词法文件句柄,我还检查了操作是否成功.请避免全局文件句柄(全局变量是坏的,mmkay?)和魔术双参数open
(它是Perl代码中许多(n可利用的)错误的来源),并且总是测试你open
的成功是否成功.
我认为将词法变量显示为文件处理程序和错误处理会更好.使用Fcntl模块中的常量也比使用魔术数字2的硬编码更好,这可能不是所有操作系统上的正确数字.
use Fcntl ':flock'; # import LOCK_* constants # open the file for appending open (my $fh, '>>', 'test.dat') or die $!; # try to lock the file exclusively, will wait till you get the lock flock($fh, LOCK_EX); # do something with the file here (print to it in our case) # actually you should not unlock the file # close the file will unlock it close($fh) or warn "Could not close file $!";
查看flock的完整文档和PerlMonks上的文件锁定教程,即使它也使用了旧式的文件句柄用法.
实际上我通常会跳过close()上的错误处理,因为如果它失败了我无能为力.
关于要锁定的内容,如果您在单个文件中工作,则锁定该文件.如果您需要同时锁定多个文件,那么 - 为了避免死锁 - 最好选择一个锁定的文件.如果这是您真正需要锁定的几个文件之一,或者您为锁定目的而创建的单独文件,这并不重要.