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 不使用共享内存?的主要内容,如果未能解决你的问题,请参考以下文章