Perlで、作成の時点でロックされているファイルを作成する方法はありますか?

StackOverflow https://stackoverflow.com/questions/6387334

  •  29-10-2019
  •  | 
  •  

質問

作成の時点で読み取りに対してロックされているファイルを作成する必要があります。そうすれば、このファイルを探しに行く可能性のある他のプロセスは、完全に記述される前に読み始めません。

私は作成できることを知っています それから それをロックしますが、これにより私は人種の状態に開かれているのではないかと心配しています。

または ここでは何も心配していませんか?書き込み用のファイルを開いてから、別のプロセスで読むために開くファイルがある場合、読み取りプロセスはファイルを閉じるまでEOFを表示しませんか?

役に立ちましたか?

解決

レースコンディションがあります >>>, 、しかし、それを使用して回避することができます +<.

# >
open(my $fh, '+<', $qfn) or die $!;
flock($fh, LOCK_EX) or die $!;
truncate($fh, 0) or die $!;
...

# >>
open(my $fh, '+<', $qfn) or die $!;
flock($fh, LOCK_EX) or die $!;
seek($fh, 0, SEEK_END) or die $!;
...

あなたが説明するシナリオにも人種的状態があります。

Writer                       Reader
=========================    =========================
- opens file
                             - opens file
                             - locks file
                             - obtains lock on file
- locks file [blocks]        - reads the file [empty]
                             - closes and unlocks file
- obtains lock on file
- writes to file
- writes to file
- closes and unlocks file

この問題を回避するための一般的な戦略は、作家を持つことです

  1. 一時ディレクトリにファイルを作成してから
  2. rename ファイルがディレクトリに入り、ファイルが完了したときに読者がモニターします。

rename アトミックアクションであるため、ファイルはディレクトリに完全に形成され、リーダーがモニターします。これには作家の協力が必要ですが、最良の解決策はそうします。

他のヒント

使用する umask(0777) ファイルを作成する前に。

ファイルシステムへのファイルのエントリは完全にアクセスできません[*](つまり、許可 ----------)、ファイルハンドルがまだ許可されている場合でも書き込みます。

それで chmod() 完了したらファイル:

my $file = 'foo.txt';
my $umask = umask(0777);    # change the umask
open(OUT, '>', $file);      # create the file 
umask($umask);              # reset the umask
print OUT "testing\n";      # put stuff in your file
close(OUT);                 # finished with that...
chmod(0644, $file);         # change the permissions

NB:これは、実際には厳格な意味では「ロック」されていません。オペレーティングシステムがファイルへのアクセスを積極的に防止します。これはファイルシステムレベルの「ハック」です。実際にファイルを開くことができない場合は、ロックされています。

*]を除く root Processe。

(FWIW、半書かれたファイルを読んでいます 意思 EOF状態になります。)

これはオペレーティングシステムでサポートされているか、そうではありません。もしそうなら、それは簡単でシンプルです。

use Fcntl   qw( O_CREAT   O_EXCL   O_WRONLY   O_EXLOCK  );

$creat_flags = (O_CREAT | O_EXCL | O_WRONLY | O_EXLOCK );

sysopen(SOMEHANDLE, $somepath, $creat_flags, 0666)
    || die "$0: couldn't sysopen $somepath with flags $creat_flags: $!";
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top