Perl IPC 不使用共享内存?

Posted

技术标签:

【中文标题】Perl IPC 不使用共享内存?【英文标题】:Perl IPC without using shared memory? 【发布时间】:2012-01-07 16:19:20 【问题描述】:

部分代码为:

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,这样我就可以向其中添加网址,但我不断得到:

无法创建信号量集:设备上没有剩余空间

这是做内核(Ubuntu 10.04 LTS)参数(SEMMNI,SEMMNS)的事情。 我增加了它们,但它仍然没有真正有用,所以我可能在这里做错了。

还有其他方式(可能是Storable 相关解决方案...)在进程之间共享数组吗?

谢谢,

【问题讨论】:

使用 'mount' 我看到了这些: /dev/shm 上没有类型 tmpfs (rw,nosuid,nodev) /var/run 上没有类型 tmpfs (rw,nosuid,mode=0755) /var/lock type tmpfs (rw,noexec,nosuid,nodev) none /lib/init/rw type tmpfs (rw,nosuid,mode=0755 【参考方案1】:

您可能已经这样做了,但最好准确确认失败的原因以及您所做的更改是否生效。要确认这确实是 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 到内存,如果你喜欢)。就像上面的线程评论一样,不要忘记使用适当的锁定。

最后,我在您的代码中没有看到任何锁定调用,那么您是否有可能有一个进程生成 URL,而其他进程以只读方式访问数据结构?如果是这样,另一种选择是通过管道将 URL 提供给子进程。但根据您通常拥有的 URL 数量的规模以及它们是否真的对孩子们来说是只读的,这个想法可能不适用。

希望能给你一些可行的选择。

【讨论】:

感谢您的回答,它应该被接受 - 在检查所有可用的工具时,线程非常适合我正在做的事情。

以上是关于Perl IPC 不使用共享内存?的主要内容,如果未能解决你的问题,请参考以下文章

IPC在两个不相关的节点js进程之间使用共享内存通信

IPC通信_共享内存

IPC:共享内存终止进程通知

使用共享内存的 IPC

Perl进程间数据共享

共享内存是最快的一种IPC方式