想象一下下面的Perl代码(这里是伪代码):
successfully acquired flock for FILEHANDLER # line 1
some error or maybe simply a call to exit() # line 2
close FILEHANDLER (which also releases the lock) # line 3
在这种情况下,我不会释放锁,因为Perl脚本在第2行结束。在这种情况下,操作系统是否发布了锁?是否看到“嘿,获得锁定的脚本崩溃了”并释放锁定?它会立即释放锁吗?此外,是否有一个Perl实例为每个脚本运行,以便明确哪个脚本崩溃/停止而不释放锁?
答案 0 :(得分:31)
在这种情况下,操作系统是否已发布锁定?
它是否看到“嘿,获得锁的脚本崩溃了”并释放了锁? 它会立即释放锁吗?
所有这些问题都取决于系统。 Perl 5没有实现文件锁定功能,它只提供flock(2)
,fcntl(2)
锁定或lockf(3)
的公共接口(取决于操作系统中可用的内容)。当程序退出时,段错误或被sigkill杀死时可能会有所不同。
Linux下的快速测试显示在正常退出条件下删除了锁:
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"'
got lock
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"'
got lock
让我们看看当die
:
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"; die "died"'
got lock
died at -e line 1.
$ perl -le 'open my $fh, ">", "f" or die $!; print flock($fh, 6) ? "got lock" : "was already locked", "\n"; die "died"'
got lock
died at -e line 1.
要获得段错误,我们需要访问C,我正在使用Inline
来获取它:
$ cat segfault.pl
#!/usr/bin/perl
use strict;
use warnings;
use Inline "C";
open my $fh, ">", "f" or die $!;
print flock($fh, 6) ? "got lock" : "was already locked", "\n";
crash();
__DATA__
__C__
void crash() {
int* ptr = NULL;
*ptr = 5;
}
$ perl segfault.pl
got lock
Segmentation fault
$ perl segfault.pl
got lock
Segmentation fault
最后,这是在发送程序时发生的事情SIGKILL
:
$ cat fork.pl
#!/usr/bin/perl
use strict;
use warnings;
$SIG{CHLD} = "IGNORE"; #auto-reap children
die "could not fork: $!" unless defined(my $pid = fork);
unless ($pid) {
#child
open my $fh, ">", "f" or die $!;
print flock($fh, 6) ? "got lock" : "was already locked", "\n";
sleep(100);
exit;
}
kill 9, $pid;
die "could not fork: $!" unless defined($pid = fork);
unless ($pid) {
#child
open my $fh, ">", "f" or die $!;
print flock($fh, 6) ? "got lock" : "was already locked", "\n";
exit;
}
$ perl fork.pl
got lock
got lock
通过这些实验,我们可以看到Linux在您关注的每个案例中都会发布锁定。
此外,是否有一个perl实例为每个脚本运行,以便明确哪个脚本崩溃/停止而不释放锁?
是的,Perl 5每个脚本有一个perl
进程。即使你分叉,孩子也会得到自己的perl
进程。线程不提供单独的perl
进程。
注意:如果父进程获得锁定并且在锁定之前没有放弃锁定,那么即使父进程退出,子进程也将具有相同的锁定。
答案 1 :(得分:2)
当程序退出时,操作系统会自动释放程序获取的所有锁,并关闭程序打开的所有文件。