为什么File::FcntlLock的l_type总是"F_UNLCK"即使文件被锁定?



下面的perl子例程使用File::FcntlLock检查文件是否已锁定。

即使文件已锁定,为什么它返回0并打印/tmp/test.pid is unlocked.

sub getPidOwningLock {
    my $filename = shift;
    my $fs = new File::FcntlLock;
    $fs->l_type( F_WRLCK );
    $fs->l_whence( SEEK_SET );
    $fs->l_start( 0 );
    $fs->l_len( 0 );
    my $fd;
    if (!open($fd, '+<', $filename)) {
        print "Could not open $filenamen";
        return -1;
    }
    if (!$fs->lock($fd, F_GETLK)) {
        print "Could not get lock information on $filename, error: $fs->errorn";
        close($fd);
        return -1;
    }
    close($fd);
    if ($fs->l_type() == F_UNLCK) {
        print "$filename is unlocked.n";
        return 0;
    }
    return $fs->l_pid();
}

文件锁定为如下(lock.sh):

#!/bin/sh
(
    flock -n 200
    while true; do sleep 1; done
) 200>/tmp/test.pid

该文件确实已锁定:

~$ ./lock.sh &
[2] 16803
~$ lsof /tmp/test.pid
COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    26002 admin  200w   REG    8,5        0 584649 test.pid
sleep   26432 admin  200w   REG    8,5        0 584649 test.pid

fcntlflock锁相互看不见。

这对于您的用例来说是一个大问题,因为您在Shell脚本中使用的flock实用程序取决于flock语义:Shell脚本运行一个flock子进程,该进程将锁定继承的文件描述符,然后退出。外壳使该文件描述符打开(因为重定向是在整个命令中),直到要释放锁。

该计划无法与fcntl一起使用,因为fcntl锁在过程之间未共享。如果有与flock相同但使用fcntl相同的实用程序,则锁会释放得太早(一旦儿童进程退出)。

对于Perl进程和Shell脚本之间的文件锁定,您可以考虑的一些选项是:

  • 将shell脚本端口到 zsh,并使用 zsh/system模块内置的 zsystem flock(注意:在文档中,尽管其名称为 flock,但在文档中声称使用fcntl
  • 在perl中重写shell脚本
  • 只需在Perl脚本中使用Flock(放弃字节范围锁定和" Get Locker PID"功能 - 但是您可以通过读取/proc/locks在Linux上模仿它)
  • 在C中使用您自己的fcntl实用程序以供壳脚本使用(使用模式将不同 - Shell脚本将必须进行背景,然后稍后杀死它以解锁 - 它将需要某种方法来告诉父母父母当它获得或无法获得锁定的过程时,这将很难,因为现在它异步发生了……也许使用某些壳具有的 coprocess 功能)。
  • 从Shell脚本运行一个小的Perl脚本进行锁定(将需要与专用fcntl实用程序相同的背景处理)

有关各种锁的功能的更多信息,请参阅使用fcntlflock锁定之间的区别。

相关内容

  • 没有找到相关文章

最新更新