2

これら 3 つのバージョンは同等ですか?

#!/usr/bin/env perl
use warnings;
use strict;
use 5.10.0;
use Fcntl qw(:flock :seek);
my $fh;

sysopen $fh, $file, O_WRONLY | O_CREAT | O_TRUNC or die $!;
flock $fh, LOCK_EX or die $!;
say $fh 'something';
close $fh;

sysopen $fh, $file, O_WRONLY | O_CREAT or die $!;
flock $fh, LOCK_EX or die $!;
seek $fh, 0, SEEK_SET or die $!;
truncate $fh, 0 or die $!;
say $fh 'something';
close $fh;

sysopen $fh, $file, O_WRONLY | O_CREAT or die $!;
flock $fh, LOCK_EX or die $!;
truncate $fh, 0 or die $!;
say $fh 'something';
close $fh;
4

1 に答える 1

2

ファイルを開いてロックし、そのロックを競合している別のプロセスが切り捨てられたファイルを見る可能性なしに切り捨てたいようです。これにはいくつかの制限があります。

  • 切り捨ての前にロックを取得する必要があります。これは、ロックを取得する前に切り捨てを行うため、最初の解決策を除外します。
  • ファイル ハンドルを別のモードで再度開くことはできません。そうしないと、ロックが失われます。これは、切り捨てを再開しても実行できないことを意味します。

したがって、理想的なソリューションには次の手順があります。

  1. ファイルは切り捨てられずに開かれます。たとえば、sysopen やオープン モード>>を使用します+<。ここでは、sysopen オプションO_TRUNCやオープン モードなどを使用してはなりません>+>
  2. ロックが取得されます。
  3. 切り捨てが実行されます。open新しいファイルハンドルを作成する場合と同様に、ここでtruncate関数を使用する必要があります。
  4. ファイルが追加モードで開かれた場合は、ファイルseekの先頭に必要です。

最初の解決策は、ロックを取得する前に切り捨てられるため、除外できます。

2 番目と 3 番目の解決策はどちらも可能ですが、seek必要ありません。

他のソリューションは regular を使用できますopen:

open my $fh, "+<", $file;  # Achtung: fails if the file doesn't exist
flock $fh, LOCK_EX;
truncate $fh;

# or:
open my $fh, ">>", $file;
flock $fh, LOCK_EX;
truncate $fh;
seek 0, 0;

多くの場合、関係のないファイルをロックとして使用することをお勧めします。これにより、再オープンの問題を回避できます。これは次のようになります。

# adapted from perldoc -f flock

sub lock {
  my $file = shift;
  open my $fh, "<", ".$file.lock";
  flock $fh, LOCK_EX;
  return $fh;
}

sub unlock {
  my $fh = shift;
  flock $fh, LOCK_UN;
}

my $lock = lock($file);
open my $fh, ">", $file;
...
unlock($lock);

もちろん、関連するすべてのプロセスは、このインターフェイスを尊重し、適切なロックファイルを作成する必要があります。

于 2013-09-15T15:49:15.620 に答える