我需要在主程序中访问通过分叉的子程序生成的哈希的内容。这里具体是我试图做的事情:
use Benchmark;
use File::Find;
use File::Basename;
use File::Path;
use Data::Dumper;
use strict;
use warnings;
print "Process ID: $$ \n";
my @PartitionRoots = qw(/nfs/dir1 /nfs/dir2 /nfs/dir3 /nfs/dir4);
my @PatternsToCheck = qw(prefix1 prefix2);
my @MatchedDirnames = qw();
my $DirCount = 0;
my $Forks = 0;
my @AllDirs = qw();
my %SweepStats = ();
foreach my $RootPath (@PartitionRoots) {
foreach my $Pattern (@PatternsToCheck) {
if (grep {-e} glob ("$RootPath/$Pattern*")) {
my @Files = glob ("$RootPath/$Pattern*");
foreach my $FileName (@Files) {
if (-d $FileName) {
$DirCount++;
push (@AllDirs, $FileName);
my $PID = fork;
if (not defined $PID) {
warn 'Could not fork!\n';
next;
}
if ($PID) {
$Forks++;
print "In the parent PID ($$), Child pid: $PID Number of forked child processes: $Forks\n";
} else {
print "In the child PID ($$)\n";
find(\&file_stats, $FileName);
print "Child ($$) exiting...\n";
exit;
}
}
}
}
}
}
for (1 .. $Forks) {
my $PID = wait();
print "Parent saw child $PID exit.\n";
}
print "Parent ($$) ending.\n";
print Dumper (\%SweepStats);
foreach my $DirName (@AllDirs) {
print ("Printing $DirName contents...\n");
foreach (@{$SweepStats{$DirName}}) {
my $uname = $_->{uname};
my $mtime = $_->{mtime};
my $size = $_->{size};
my $file = $_->{file};
print ("$uname $mtime $size $file\n");
}
}
sub file_stats {
if (-f $File::Find::name) {
my $FileName = $_;
my $PathName = dirname($_);
my $DirName = basename($_);
my $uid = (stat($_))[4];
my $uname = getpwuid($uid);
my $size = (stat($_))[7];
my $mtime = (stat($_))[9];
if (defined $uname && $uname ne '') {
push @{$SweepStats{$FileName}}, {path=>$PathName,dir=>$DirName,uname=>$uname,mtime=>$mtime,size=>$size,file=>$File::Find::name};
} else {
push @{$SweepStats{$FileName}}, {path=>$PathName,dir=>$DirName,uname=>$uid,mtime=>$mtime,size=>$size,file=>$File::Find::name};
}
}
return;
}
exit;
字符串
.但是Dumper是空的,所以紧接着的解引用和打印也是空的。我知道文件统计信息收集工作正常,因为如果我用print语句替换“push @{$SweepStats{$FileName}}”语句,我就能看到预期的结果。我只需要从全局级别正确访问哈希值,但是我不能完全正确。我在这里做错了什么?有各种各样的帖子都是关于将散列传递给子程序的,但不是相反。
2条答案
按热度按时间nhn9ugyo1#
fork调用创建了一个新的独立进程。这个子进程和它的父进程不能互相写数据。所以为了在父进程和子进程之间交换数据,我们需要使用一些进程间通信(IPC)机制。
到目前为止,使用一个处理细节的库是最容易的,Parallel::ForkManager似乎在这里非常合适,因为它提供了一种简单的方法来将数据从子进程传递回父进程,并且它有一个简单的队列(将同时进行的进程数量限制在给定的数量)。
下面是一些工作代码,注解如下
字符串
评论
%stats
hash是File::Find
存储它找到的数据所必需的,需要在所有循环之外声明,以便在sub中看到它。因此,它被所有子进程继承,但每个子进程都有自己的副本,我们不必担心数据重叠等问题有许多库可以用来显示复杂的数据结构,我使用Data::Dump,目的是简单地打印出来
型
其紧凑的输出,而最广泛使用的是核心Data::Dumper
型
它也“理解”数据结构(所以你可以大多
eval
他们回来)。(Note:在这种情况下,可能会有 * 很多 * 输出!所以重定向到一个文件,或者在第一次迭代后退出这些循环,看看它是如何进行的。
†当一个进程被分叉时,父进程的变量和数据都可以被子进程使用。出于效率的考虑,它们不会立即被复制,所以最初子进程确实会读取父进程的数据。但是父进程或子进程中的
fork
调用之后生成的任何数据都不能被其他进程看到。bgtovc5b2#
试试这个模块:IPC::Shareable。它是由
perldoc perlipc
推荐的,你可以在这里找到你问题的答案。