为什么即使文件被锁定,File :: FcntlLock的l_type也总是“F_UNLCK”?

时间:2017-02-15 15:07:05

标签: linux perl flock fcntl

下面的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 $filename\n";
        return -1;
    }

    if (!$fs->lock($fd, F_GETLK)) {
        print "Could not get lock information on $filename, error: $fs->error\n";
        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

1 个答案:

答案 0 :(得分:6)

fcntlflock锁彼此不可见。

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

该计划无法与fcntl一起使用,因为fcntl锁不会在进程间共享。如果有一个与flock相同但使用fcntl的实用程序,则锁定将过早释放(一旦子进程退出)。

为了协调perl进程和shell脚本之间的文件锁定,您可以考虑以下几个选项:

  • 将shell脚本移植到zsh并使用zsystem flock模块中的zsh/system内置版(注意:在其声称使用fcntl的文档中尽管名称如此是flock
  • 在perl
  • 中重写shell脚本
  • 只需在perl脚本中使用flock(放弃字节范围锁定和&#34;获取锁定器PID&#34;功能 - 但您可以通过阅读/proc/locks来模拟Linux上的内容)
  • 在C语言中编写自己的fcntl实用程序以便在shell脚本中使用(使用模式将不同 - shell脚本必须对其进行后台处理,然后在以后将其解除以解锁 - 并且需要某种方式告诉父进程何时获得或未能获得锁定,这将很难,因为它现在异步发生...可能使用某些shell具有的 coprocess 功能。
  • 从shell脚本运行一个小的perl脚本来进行锁定(需要与专用的fcntl实用程序需要相同的后台处理)

有关不同类型锁的功能的更多信息,请参阅What is the difference between locking with fcntl and flock