文件锁定和输入解锁

时间:2012-05-14 21:37:50

标签: perl locking sleep

我有一个子程序,其中我试图独占锁定一组文件(一次一个)并保持该锁定一定的给定时间(通过sleep)。我正在尝试添加让用户按下某个键(例如回车键)时解锁当前锁定(休眠)文件的功能。我只是不确定要让它发挥作用的方向。每次尝试使用STDIN并检查\ n都没有奏效。感谢。

以下是子程序。我切换到我想要文件的目录。从1创建文件到指定了多少文件。对于每个文件,都会打开一个独占锁,然后在指定的时间内休眠。

编辑:不提这个是我的错,但是这个脚本将在Windows环境中运行。理想情况下,我喜欢不需要Perl中未包含的额外模块安装的解决方案。 (这是因为breq中的模块'解决方案不支持Windows)。谢谢。

sub lockFiles{
    #creates files that are locked for a specific amount of seconds.
    chdir("lock files")or die "Unable to enter dir $!\n";
    opendir(DIR,".") or die "Can't open the current directory: $!\n";

    #file iterator
    my $i=1;
    #for each file lock it and sleep the given amount of time
    while($i<=$numberOfFiles){
        open FILE, ">>", "test$i.txt" or die $!;
        flock(FILE, 2) or die "Could not lock test$i.txt\n";
        print "test$i.txt locked, locking for $timeToSleep seconds\n";
        print "Press ctrl+c to kill this\n";

        sleep($timeToSleep);

        $i++;
        close(FILE);
    }
    closedir(DIR);
    #change back to the parent folder
    chdir("..") or die "Can't change to the directory: $!\n";
    print "subRoutine lockFiles success\n";
}

2 个答案:

答案 0 :(得分:1)

我没有安装带有Perl的Windows机器来检查它是否有效,但是Term :: ReadKey上的文档暗示它应该。 Term :: ReadKey是一个提供非阻塞和定时读取功能的模块。它有一些有限的Windows支持。

use Time::HiRes qw(time sleep);
use Term::ReadKey;

sub wait_for_key {
    my $timeout = shift;

    my $started = time();
    while (1) {
        last if $started + $timeout < time();

        my $str = '';
        while (my $char = ReadKey(-1)) {
            $str .= $char;
        };

        last if $str =~ m/\n/s;
        sleep 0.1;
    }
}
但是,我确信有更好的方法可以做到这一点。也许有佩戴perl-on-windows经验的人会出现。

诅咒你,Windows。在任何其他系统上,上面的代码如下所示:

sub wait_for_key { ReadLine(shift) }

答案 1 :(得分:0)

尝试那样的事情:

use Sys::SigAction qw(sig_alarm set_sig_handler);

sub wait_for_key {
    my $timeout = shift;

    eval {
        my $sa = set_sig_handler('ALRM', sub { die "enough" }, {} );
        eval {
            sig_alarm($timeout);
            my $keyboard = <>;
            sig_alarm(0);
        };
        sig_alarm(0);
    }
}

此功能将在任何输入(“Enter”键)或超时后退出,因此您只需调用它而不是sleep()。基本思路是:

1)无限等待输入
2)但是为你需要的超时设置一个警报。

看起来很邪恶,但工作正常。

这实际上是一种通过超时调用某些代码的通用方法 - 只需使此函数接受第二个参数即函数引用,并调用该引用而不是my $keyboard = <>行。而且,检查错误并完成我在此示例中遗漏的所有无聊内容。