Perl 锁定文件进行读写操作
我正在编写一个应用程序,其中两个进程需要更新同一个文件Perl 锁定文件进行读写操作,perl,Perl,我正在编写一个应用程序,其中两个进程需要更新同一个文件file.txt。这有可能同时发生,所以我应该实现一些锁定框架 每个进程都需要首先读取所有file.txt,对其进行处理,然后写出file.txt的修改版本。因此,锁应该在第一次读取文件之前获得,并在写入之后释放。我在Fcntl中签出了flock,但它似乎只能锁定一个文件句柄,因此在第一次读取后锁就丢失了(因为我必须先关闭文件,然后才能重新打开它以便稍后写入) 另外,如果一个进程锁定了该文件,而另一个进程试图锁定它,则它不应该中止,而是实现某
file.txt
。这有可能同时发生,所以我应该实现一些锁定框架
每个进程都需要首先读取所有file.txt
,对其进行处理,然后写出file.txt
的修改版本。因此,锁应该在第一次读取文件之前获得,并在写入之后释放。我在Fcntl
中签出了flock
,但它似乎只能锁定一个文件句柄,因此在第一次读取后锁就丢失了(因为我必须先关闭文件,然后才能重新打开它以便稍后写入)
另外,如果一个进程锁定了该文件,而另一个进程试图锁定它,则它不应该中止,而是实现某种非忙等待,直到另一个文件释放对该文件的锁定
如何最好地实现此锁定方案?有我可以使用的CPAN模块吗?可以满足您的需要。请注意,这是一种协作措施,因此其他进程将需要使用相同的系统,否则将无法阻止它们对文件执行自己喜欢的操作
关于丢失文件的锁,您有两个明显的选择
- 获取单独文件上的锁,该文件仅用于控制对主文件的访问。这可能是最整洁的方法
- 使用
+模式打开具有读写访问权限的文件将执行您需要的操作。请注意,这是一种协作措施,因此其他进程将需要使用相同的系统,否则将无法阻止它们对文件执行自己喜欢的操作 关于丢失文件的锁,您有两个明显的选择
- 获取单独文件上的锁,该文件仅用于控制对主文件的访问。这可能是最整洁的方法
- 使用
+模式打开具有读写访问权限的文件参见问题的OP试图以附加模式打开文件,然后以读/写模式打开文件,但概念是相同的。给定锁是建议性的(在unix上)是否可以使用单独的锁文件?@Sobrique是的,单独的锁文件似乎是个好主意。我想知道,如果文件被锁定,如何实现进程不忙着等待?@HåkonHægland:一个被暂停等待被授予
的进程不忙着等待,因此,您的进程可以安全地请求对锁定文件的独占锁定,并确保在flock
调用返回时,它对数据文件具有独占访问权。它不会重复检查锁。这个问题的答案是,试图在附加模式下打开一个文件,然后在读/写模式下打开,但概念是一样的。给定锁是建议性的(在unix上)您可以使用单独的锁文件吗?@Sobrique是的,单独的锁文件似乎是个好主意。我想知道,如果文件被锁定,如何实现进程不忙着等待?@HåkonHægland:一个被暂停等待被授予flock
的进程不忙着等待,因此,您的进程可以安全地请求对锁定文件的独占锁定,并确保在flock
调用返回时,它对数据文件具有独占访问权。它不会重复检查第一个代码段中的锁,$data\u文件和$lock\u文件可以是同一个文件。您可以简单地执行flock
打开我的$lock\u fh',在第一个代码段中,$data\u文件和$lock\u文件可以是同一个文件。你只需打开我的$lock\u fh,'
use Fcntl qw/ :flock :seek /;
use strict; use warnings; use 5.010; use autodie; use Fcntl qw/ :flock /; my ($data_file, $lock_file) = qw/ data.txt lockfile.lock /; open my $lock_fh, '<', $lock_file; flock $lock_fh, LOCK_EX; open my $data_fh, '<', $data_file; chomp(my $record = <$data_fh>); open $data_fh, '>', $data_file; print $data_fh ++$record, "\n"; close $data_fh; close $lock_fh;
use strict; use warnings; use 5.010; use autodie; use Fcntl qw/ :flock :seek /; my $data_file = 'data.txt'; open my $data_fh, '+<', $data_file; flock $data_fh, LOCK_EX; chomp(my $record = <$data_fh>); seek $data_fh, 0, SEEK_SET; truncate $data_fh, 0; print $data_fh ++$record, "\n"; close $data_fh;