4

我需要在创建时创建一个锁定读取的文件,以便其他可能寻找该文件的进程在完全写入之前不会开始读取它。

我知道我可以创建然后锁定它,但我担心这会让我面临竞争条件。

还是我在这里什么都不担心?如果我打开一个文件进行写入,然后打开它以使用另一个进程读取,那么在写入过程关闭文件之前,读取过程是否永远不会看到 EOF?

4

3 回答 3

8

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 条件。)

于 2011-06-17T14:29:35.583 回答
8

和存在竞争条件>>>但可以使用+<.

# >
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

  1. 在临时目录中创建文件,然后
  2. rename当文件完成时,将文件放入阅读器监控的目录中。

rename是一个原子动作,因此文件将在阅读器监视的目录中完全形成。这需要作者的合作,但最好的解决方案会。

于 2011-06-17T14:50:49.060 回答
3

您的操作系统要么支持此功能,要么不支持。如果是的话,这很容易和简单。

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: $!";
于 2011-06-17T16:06:03.353 回答