Perl:将序列化哈希管道传递给分叉进程

car*_*rot 2 perl serialization fork storable

我不知道我的代码有什么问题.我正在尝试序列化父级内部的哈希并将其传递给fork,它应该在其中进行反序列化.

#!/usr/bin/perl
use strict;
use warnings;
use Storable qw(freeze thaw);
use IO::Pipe;

my $pipe_to_fork = IO::Pipe->new();

my $fork = fork;
if ($fork == 0) { # actual fork scope
  $pipe_to_fork->reader();
  my $hash_serialized = <$pipe_to_fork>; # wait and retrieve the serialized hash from parent
  chomp $hash_serialized;
  my %hash_rebuild = %{thaw($hash_serialized)}; # deserialize the retrieved serialized hash
  exit;
}

my %hash = ('key1' => "val1", 'key2' => "val2");

$pipe_to_fork->writer();
$pipe_to_fork->autoflush(1);

my $hash_serialized = freeze(\%hash); # serialize the hash
print $pipe_to_fork $hash_serialized."\n";
sleep 5;

exit;
Run Code Online (Sandbox Code Playgroud)

...产生以下错误:

Can't use an undefined value as a HASH reference at ./fork_serialize.pl line 14, <GEN0> line 1.
Run Code Online (Sandbox Code Playgroud)

管道有问题吗?似乎thaw没有反序列化检索到的标量值.也许检索到的标量值不正确.

我试图做一些没有分叉或管道的半圆形东西,它的工作:

#!/usr/bin/perl
use strict;
use warnings;
use Storable qw(freeze thaw);

my %hash = ('key1' => "value1", 'key2' => "value2");
my $hash_serialized = freeze(\%hash);
my %hash_rebuild = %{thaw($hash_serialized)};

print $hash_rebuild{'key2'}."\n";
Run Code Online (Sandbox Code Playgroud)

没有太大的逻辑差异,他?如果有人能够解释我更多这种行为,那就太好了.

小智 6

麻烦的是你正在尝试使用基于行的协议("\n"在写入端附加,使用<>chomp在读取端)但你的数据不是文本,并且可以包含它自己的"\n"s,所以你的读者在第一个停止并砍掉它.

您需要使用一些其他方法来发送序列化数据的结束信号,例如,您可以关闭写端的管道并继续执行直到读取端的EOF.事实上,Storable有一对针对这种情况设计的功能:store_fdfd_retrieve.他们将以没有EOF的方式检测末端进行转移,因此您可以保持管道打开以进行更多转移.

这是使用以下fd函数的程序内容的一个版本Storable:

if ($fork == 0) { # actual fork scope
  $pipe_to_fork->reader();
  my %hash_rebuild = %{fd_retrieve($pipe_to_fork)}; # deserialize the retrieved serialized hash
  use Data::Dumper;$Data::Dumper::Useqq=1;print Dumper \%hash_rebuild;
  exit;
}

my %hash = ('key1' => "val1", 'key2' => "val2");

$pipe_to_fork->writer();
$pipe_to_fork->autoflush(1);

store_fd(\%hash, $pipe_to_fork);
Run Code Online (Sandbox Code Playgroud)