我不知道我的代码有什么问题。我正在尝试序列化父级内部的哈希并将其传递给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;
...产生以下错误:
Can't use an undefined value as a HASH reference at ./fork_serialize.pl line 14, <GEN0> line 1.
管道有问题吗?似乎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";
没有太大的逻辑差异,他?如果有人能够更多地向我解释这种行为,那就太好了。
答案 0 :(得分:6)
问题是您尝试使用基于行的协议(在写入端附加"\n"
,在读取端使用<>
和chomp
但是您的数据不是文本,可以包含自己的"\n"
,因此您的读者会在第一个停止并将其删除。
您需要使用其他一些方法来发信号通知序列化数据的结尾,例如,您可以关闭写入端的管道并继续执行直到读取端的EOF。事实上,Storable
有一对针对这种情况设计的功能:store_fd
和fd_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);
答案 1 :(得分:4)
问题是你假设散列是freezed
到一行。但情况并非总是如此,因为$hash_serialized
可能是一个包含多个\n
s的字符串。
因此,不应只读取子行中的一行,而应该读取直到EOF并连接所有行。
#!/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;
$hash_serialized .= $_ while (<$pipe_to_fork>);
my %hash_rebuild = %{thaw($hash_serialized)}; # deserialize the retrieved serialized hash
print $hash_rebuild{key1};
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;
exit;
输出: val1