Perl IPC没有使用共享内存?

时间:2012-01-07 16:19:21

标签: linux perl ipc

部分代码是:

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相关的解决方案......)在进程之间共享一个数组?

谢谢,

1 个答案:

答案 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提供给子流程。但是根据您通常拥有的网址数量以及儿童是否真的只读这个网址,这个想法可能不适用。

希望能为您提供一些可行的选择。