我需要在创建时创建一个锁定读取的文件,以便其他可能寻找该文件的进程在完全写入之前不会开始读取它。
我知道我可以创建然后锁定它,但我担心这会让我面临竞争条件。
还是我在这里什么都不担心?如果我打开一个文件进行写入,然后打开它以使用另一个进程读取,那么在写入过程关闭文件之前,读取过程是否永远不会看到 EOF?
我需要在创建时创建一个锁定读取的文件,以便其他可能寻找该文件的进程在完全写入之前不会开始读取它。
我知道我可以创建然后锁定它,但我担心这会让我面临竞争条件。
还是我在这里什么都不担心?如果我打开一个文件进行写入,然后打开它以使用另一个进程读取,那么在写入过程关闭文件之前,读取过程是否永远不会看到 EOF?
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
注意:这实际上并不是严格意义上的“锁定”,操作系统主动阻止访问文件。这是文件系统级别的“hack” - 如果您实际上无法打开文件,那么它就会被锁定。
[*] 处理除外root
。
(FWIW,读取半写文件将导致 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
避免这个问题的一个常见策略是让 writer
rename
当文件完成时,将文件放入阅读器监控的目录中。rename
是一个原子动作,因此文件将在阅读器监视的目录中完全形成。这需要作者的合作,但最好的解决方案会。
您的操作系统要么支持此功能,要么不支持。如果是的话,这很容易和简单。
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: $!";