繁体   English   中英

在Perl中的文件系统事件上派生子进程

[英]Forking child processes on file system events in perl

我有一个用Perl编写的守护进程,它使用Inotify2来监视目录中的传入文件。 在每个文件到达时,守护程序将派生一个子进程。 现在,似乎同时有太多文件到达(因此派生了太多分叉),因为我的日志文件中出现此错误:

Cannot allocate memory at notifyd.pl line ...

这是fork()的结果。

基本上我有以下代码:

    my $inotify = new Linux::Inotify2() or die($!);

    foreach my $k (@PATHS) {
        $inotify->watch($k,
IN_MOVE_SELF|IN_DELETE_SELF|IN_CLOSE_WRITE, \&watcher) or die($!);
    }

    $inotify->blocking(1) or die($!);

    for(;;) {
        $inotify->poll() or die($!);
    }

使用watcher函数先执行fork然后执行execv:

sub watcher {
        my $e = shift;
        my $pid = fork();
        if(!defined $pid) {
            print "[ERROR]", $!;
        }
        elsif($pid == 0) {
            my @args = ($e->fullname, $e->mask);
            exec($childprocess, @args) or die($!);
        }
}

我不能通过不分进程来错过事件。

有人建议我如何改善它并确保fork不会失败吗?


编辑:子进程一旦退出就好像变成了僵尸,因为守护程序不会响应SIGCHLD。 因此,很多僵尸子进程可能是fork()失败的原因。 守护程序现在执行$SIG{CHLD} = 'IGNORE'; 在分叉之前。

通过添加另一层间接解决该问题。

收到事件时,将文件名放入作业队列 当合理的资源可用时,队列开始处理文件的新作业。 这种方案保证了事件将最终被执行,只是不是立即全部执行。

使用更强大的后台流程管理器,例如Forks::Super

例如,此设置一次最多可以运行10个fork。 当所有10个fork都忙时出现的新请求将被放入队列。 队列中的作业将在其他后台进程完成且资源可用时运行。

use Forks::Super  MAX_PROC => 10, ON_BUSY => 'queue';

...

sub watcher {
    my $e = shift;
    fork {
       sub => sub {
           my @args = ($e->fullname, $e->mask);
           exec($childprocess, @args) or die($!);
       }
    };
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM