我有一个用Perl编写的使用Inotify2观察传入文件的目录的守护进程。每个文件到达后,守护进程将分叉一个子进程。现在,似乎太多的文件正在到达的同时(因此太多叉),因为我在日志文件中得到这个错误:在perl中分页文件系统事件的子进程
Cannot allocate memory at notifyd.pl line ...
这是叉()的结果。
基本上我有以下代码:
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($!);
}
与守望功能做叉,然后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($!);
}
}
我不能用不派生进程错过的事件。
有没有人有建议如何我可以改善这一点,并确保叉不会失败?
编辑:它看起来像子进程变成僵尸一旦他们退出,因为守护进程不会响应SIGCHLD。所以很多僵尸子进程可能是fork()失败的原因。守护进程现在在分叉之前执行$SIG{CHLD} = 'IGNORE';
。
如果您有很多文件更改,则耗尽资源相当容易,并且根据您的使用情况,它是dos攻击的一个向量。您应该使用cpan上的某个事件循环来处理这些事件。一个好的起点可能是看AnyEvent。 – 2012-03-22 15:35:29
你确定fork()失败吗?您(部分)存在的错误消息看起来像是来自'die'或'warn',但是如果fork失败(即,如果$ pid未定义),则显示的代码将不会生成该输出。 – pilcrow 2012-03-22 15:50:24
是的,消息来自这部分代码: if(!defined $ pid){print“[ERROR]”,$ !; } – 2012-03-22 15:53:15