Perl全局变量在子进程中修改后未更新的问题及解决办法
Perl进程计数问题分析与解决
问题场景
代码片段
my $kill=0; my @array1 = ("abc", "def","ghi"); &runSmokesAndMonitor; sub runSmokesAndMonitor { foreach my $smokeTestVarDirName (@array1) { if ($pid =fork()) { print "parent\n"; ### Have some other action items as well here in parent } else { $kill++; print "Value of kill is $kill\n"; exit 0; } } }
实际输出
parent Value of kill is 1 parent Value of kill is 1 parent Value of kill is 1
期望输出
parent Value of kill is 1 parent Value of kill is 2 parent Value of kill is 3 parent
问题原因
核心是fork的进程复制机制:调用fork()创建子进程时,系统会完全复制父进程的内存空间,包括所有变量的当前值。每个子进程启动时,$kill的值都是父进程里初始的0,子进程执行$kill++后变成1,但这个修改只存在于当前子进程的独立内存中,不会同步回父进程,也不会被其他子进程共享,所以每个子进程打印的都是1。
实现预期效果的方案
方案1:父进程预维护计数(简单直接)
既然子进程会复制父进程的变量值,让父进程在fork()之前先递增$kill,这样每个子进程复制到的就是已经更新后的计数,直接打印即可。最后父进程补打一行parent对应期望输出的末尾:
my $kill=0; my @array1 = ("abc", "def","ghi"); runSmokesAndMonitor(); sub runSmokesAndMonitor { foreach my $smokeTestVarDirName (@array1) { $kill++; # 父进程先更新计数 if ($pid =fork()) { print "parent\n"; } else { print "Value of kill is $kill\n"; exit 0; } } # 最后补充父进程的输出 print "parent\n"; }
方案2:共享内存(适用于复杂进程间共享场景)
如果需要子进程之间、子父进程之间双向共享变量,可以用Perl的IPC::Shareable模块实现共享内存:
use IPC::Shareable; # 将$kill绑定到共享内存 my $kill; tie $kill, 'IPC::Shareable', undef, { create => 1, destroy => 1 }; $kill = 0; my @array1 = ("abc", "def","ghi"); runSmokesAndMonitor(); sub runSmokesAndMonitor { foreach my $smokeTestVarDirName (@array1) { if ($pid =fork()) { print "parent\n"; } else { $kill++; print "Value of kill is $kill\n"; exit 0; } } print "parent\n"; }
使用前需要先安装模块:cpan IPC::Shareable 或 cpanm IPC::Shareable。
内容的提问来源于stack exchange,提问作者PPP
相关产品推荐
相关产品推荐

