我有一個用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