部分代码是:
sub _getPages {
my $self = shift;
my $rel_url = lc(shift);
my @turls = ();
my $urls = [];
my $ipc_share = tie $urls, 'IPC::Shareable',undef, { destroy => 1 };
foreach my $stag (@{$self->{SUPP_TAGS}}) {
push(@{$urls}, map { lc($self->_normalizeSupportURL($_->url(),
$self->{MECH_O}->getGlobalMechInstance()->uri->authority,
$self->{MECH_O}->getGlobalMechInstance()->uri->scheme)) }
grep { ((index($_->url,$rel_url) > -1) || ($_->url =~ m{^/})) &&
$_->url !~ m/answer|mailto:/i }
$self->{MECH_O}->getGlobalMechInstance()->find_all_links( text_regex => qr/$stag/i ),
$self->{MECH_O}->getGlobalMechInstance()->find_all_links( name_regex => qr/$stag/i ),
$self->{MECH_O}->getGlobalMechInstance()->find_all_links( url_abs_regex => qr/$stag/i ));
}
@{$urls} = uniq(@{$urls});
foreach my $url (@{$urls}) {
if (!exists($self->{UNQ_URLS}->{lc($url)})) {
$self->{UNQ_URLS}->{lc($url)} = 1;
$self->{SUPP_PROC}->start and next;
if (eval {$self->{MECH_O}->getGlobalMechInstance()->get($url); } ) {
push(@{$urls}, map { lc($self->_normalizeSupportURL($_->url(),
$self->{MECH_O}->getGlobalMechInstance()->uri->authority,
$self->{MECH_O}->getGlobalMechInstance()->uri->scheme)) }
grep { ((index($_->url,$rel_url) > -1) || ($_->url =~ m{^/}) ||
$_->url =~ m/\d+\.\d+\.\d+\.\d+/ ) &&
$_->url !~ m/answer|mailto:/i }
$self->{MECH_O}->getGlobalMechInstance()->find_all_links( text_regex => qr/chat/i ),
$self->{MECH_O}->getGlobalMechInstance()->find_all_links( name_regex => qr/chat/i ),
$self->{MECH_O}->getGlobalMechInstance()->find_all_links( url_abs_regex => qr/chat/i ));
}
$self->{SUPP_PROC}->finish;
}
}
$self->{SUPP_PROC}->wait_all_children;
return uniq(@{$urls});
}
基本上,我想要做的是在进程之间共享$urls
,所以我可以添加url,但我一直得到:
无法创建信号量集:设备上没有剩余空间
这是做内核(Ubuntu 10.04 LTS)参数(SEMMNI,SEMMNS)的事情。 我增加了它们,但它仍然没有用,所以我可能在这里做错了。
还有另一种方法(可能是Storable
相关的解决方案......)在进程之间共享一个数组?
谢谢,
答案 0 :(得分:4)
您可能已经这样做了,但确切地确定失败的内容以及您所做的更改是否生效总是好的。要确认这是否真的是semget()返回ENOSPC,您可以使用以下命令运行它:
strace -ooutfile CMD
然后在outfile
中查找ENOSPC以确认哪个系统调用返回了它。
要确认调整SEMMNI和SEMMNS的工作情况,您可以:
cat /proc/sys/kernel/sem
(正如man proc所说,SEMMNI是第四个领域,SEMMNS是第二个领域)。
现在,要解决“我还能用什么?”的问题。直接,这里有一些选择:
我的第一选择:使用线程。您没有显示启动其他进程的代码,但由于您在它们之间共享Perl数组,我怀疑所有进程都运行相同的Perl脚本(或者代码可以这样编写)。因此,使用threads而不是分叉进程,并使用线程锁定原语在线程之间共享@urls
数组。我说这是我的第一选择,因为多线程更常用于线程,而不是分叉,所以有很多很好的例子,可用的模块有很多用处(而且它们通常不依赖于Sys V接口)。
我的第二选择是使用File::Map在进程之间共享数据。这又避免了Sys V接口,并且可能与共享内存一样快,因为系统当然会将共享文件的页面缓存在RAM中(您甚至可以要求系统将 pin 文件转换为RAM,如果你喜欢)。与上面的线程评论一样,不要忘记使用适当的锁定。
最后,我没有在您的代码中看到任何锁定调用,因此您可能有一个进程生成URL而其他进程只能以只读方式访问数据结构吗?如果是这样,另一种选择是通过管道将URL提供给子流程。但是根据您通常拥有的网址数量以及儿童是否真的只读这个网址,这个想法可能不适用。
希望能为您提供一些可行的选择。