我需要在創建時創建一個鎖定爲讀取的文件,以便可能要查找此文件的其他進程在完全寫入之前不會開始讀取它。有沒有辦法在Perl中創建一個在創建時鎖定的文件?
我知道我可以創建並且然後鎖定它,但是我擔心這會讓我面對競爭條件。
或我在這裏擔心什麼?如果我有一個打開文件的文件,然後打開它以便與另一個進程一起讀取,那麼在寫入進程關閉文件之前,讀取進程是否從不會看到EOF?
我需要在創建時創建一個鎖定爲讀取的文件,以便可能要查找此文件的其他進程在完全寫入之前不會開始讀取它。有沒有辦法在Perl中創建一個在創建時鎖定的文件?
我知道我可以創建並且然後鎖定它,但是我擔心這會讓我面對競爭條件。
或我在這裏擔心什麼?如果我有一個打開文件的文件,然後打開它以便與另一個進程一起讀取,那麼在寫入進程關閉文件之前,讀取進程是否從不會看到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
一個共同的策略來避免這個問題是有作家
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
注意:這實際上不是嚴格意義上的,其中操作系統積極阻止對文件的訪問「鎖定」。這是一個文件系統級別的「黑客攻擊」 - 如果你實際上無法打開文件,那麼它就被鎖定了。
[*]除了root
processesse。
(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: $!";
http://perl.plover.com/yak/flock/samples/slide011.html – daxim
@daxim這只是一個_advisory_鎖 - 它不會阻止流程,不遵循正常打開信號燈語義文件。 – Alnitak