[英]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.