在 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对$share
object的拷贝被销毁,导致底层系统资源被销毁,因为你使用了-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};
}
我有一个 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对$share
object的拷贝被销毁,导致底层系统资源被销毁,因为你使用了-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};
}