2013-11-04 26 views
2

我不知道什么是错我的代码。我试图序列化一个哈希内部的散列,并将其传递给叉,它应该被反序列化。的Perl:管一个序列化的哈希分叉过程

#!/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不会反序列化检索到的标量值。也许检索到的标量值不正确。

我一直试图做一些事情semilar不分叉或管道,其工作:

#!/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"; 

没有太大的差异逻辑的,他?如果有人能更多地解释我的这种行为,这将是很好的。

+3

检查发送和接收的字节数是相同的。 – tlrrd

回答

6

麻烦的是,你正在尝试使用基于行的协议(在写入侧追加"\n",读出侧用<>chomp),但你的数据不是文本,并且可以包含自己的"\n"小号所以你的读者停在第一个,然后把它关掉。

您需要使用信令序列化数据的末尾的其他方法,例如,你可以关闭上写结束的管道,并保持在读端走,直到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); 
+0

谢谢!这真的解释了很多,它现在正在工作。我已经有了一些线索,字符串中的某些字符可能会干扰每行读取的使用。 – carrot

+0

我不是故意将我的调试'Data :: Dumper'放在那里......但它没有造成任何伤害,所以我现在不会删除它。 –

+0

我没有把Data :: Dumper这行代码放到我的代码中;) - 但是如果我需要进一步的调试,我可能会使用它。 – carrot

4

的问题是,你假定哈希是freezed成一个单一的线。但情况并非总是如此,因为$hash_serialized可能是一个包含多个\n的字符串。

因此,而不是阅读的孩子边只有一条线,你应该阅读,直到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; 

Output: val1

+0

也谢谢,但Wumpus Q. Wumbley的解决方案我觉得有点更好。尽管如此,它是一个值得注意的替代方案,并且可以进一步解释整个事情。 – carrot