2013-11-04 31 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