在 IPC::ShareLite 对象中存储多个项目

Store multiple items in IPC::ShareLite object

我有一个 Perl 程序,它分叉子进程并处理其中的 N 个项目,之后我需要 return 这些处理过的项目到主进程。

从多个可用的IPC选项到return处理的项目到主进程,IPC::ShareLite似乎是最简单的,但我不确定它是否支持在一个共享对象中存储多个项目.

这是该程序的一个片段,但它不起作用:

use IPC::ShareLite;

# create shared object in main process
my $share = new IPC::ShareLite(
    -key     => 1234,
    -create  => 'yes',
    -destroy => 'yes'
) or die $!;

# fork subprocesses, process and store N items in shared object
$share->store($member);

# After subprocesses finish, fetch items in main process
my $members_size = scalar @$members_ref;
@$members_ref = ();
while ($members_size > 0) {
    my $member = $share->fetch();
    push @$members_ref, $member;
    $members_size--;
}

上面的代码在 my $member = $share->fetch();:

上出现了相当模糊的错误

IPC::ShareLite fetch() error: Invalid argument at ...

是否可以按我的意图使用 IPC::ShareLite 对象,或者它只能容纳一件物品?

您正在使用 fork 创建 child,并且此 child 获得了 $share object 的副本。当child退出时,child对$shareobject的拷贝被销毁,导致底层系统资源被销毁,因为你使用了-destroy => 'yes' .

一般来说,您希望在 执行分叉后 使用析构函数创建 object。

但是在创建IPC::ShareLite object时,您通常希望留下密钥让系统为您选择密钥,但您需要在创建分叉之前这样做。

解决方法

在 child 中执行以下操作:

$share->destroy(0);

更好的解决方案

由于模块的正常使用模式涉及创建由 child 进程继承的 object,因此模块应该处理这种情况。

为此,您应该让模块的维护者更改模块,以便仅当当前 PID 与创建 $share 的 PID 相同时才会发生销毁。

sub _initialize {
  ...
  $self->{pid} = $$;   # ADD
  ...
}

sub DESTROY {
  my $self = shift;

  #destroy_share( $self->{share}, $self->{destroy} )                           # REMOVE
  destroy_share( $self->{share}, $self->{pid} == $$ ? $self->{destroy} : 0 )   # ADD
   if $self->{share};
}