2014-08-29 83 views
2

我想等待两个进程(或更多)完成或计时器倒计时。计时器倒计时将在终端窗口中输出。例如:等待有超时的子进程

use warnings; 
use strict; 
use feature qw(say); 

my $pid1 = fork(); 
if ($pid1 == 0) { 
    runTask1(); 
    exit 0; 
} 

my $pid2 = fork(); 
if ($pid2 == 0) { 
    runTask2(); 
    exit 0; 
} 

my $timer = startTimer(); 

say "Waiting for child processes.."; 
my $counter = 20; 
my $i  = 0; 
while (1) { 
    my $pid = wait; 
    last if ($pid == -1); 
    if ($pid == $timer) { 
     $counter--; 
     say $counter; 
     $timer = startTimer(); 
    } else { 
     say "Child with PID=$pid finished.."; 
     $i++; 
     last if $i == 2; 
    } 
} 

say "Done."; 

sub startTimer { 

    my $pidTimer = fork(); 
    if ($pidTimer == 0) { 
     sleep 1; 
     exit 0; 
    } 
    return $pidTimer; 
} 

sub runTask1 { 
    sleep 10; 
    exit 0; 
} 

sub runTask2 { 
    sleep 5; 
    exit 0; 
} 

我对这种方法表示担心的是,我创建了一个分叉子进程的计时器,这似乎有点小题大做。这是必要的,还是有一个更简单的方法?

回答

4

看看alarm() - 在指定的超时后触发一个kill信号ALRM。 Which'll要么只是杀死进程,也可以使用:

$SIG{'ALRM'} = \&some_sub_to_handle_alarms; 

alarm()不会传播到派生的进程,所以你可以把它放在你的“父”,所以它只是超时等待的孩子。

虽然你可能不需要fork你的pidTimer,但你可以让你的主进程坐在一个循环中。

下面演示:

use strict; 
use warnings; 
use feature qw(say); 

my $pid1 = fork(); 
if ($pid1 == 0) { # Simulated Task 1 
    sleep 10; 
    exit 0; 
} 

my $pid2 = fork(); 
if ($pid2 == 0) { # Simulated Task 2 
    sleep 5; 
    exit 0; 
} 

say "Waiting for child processes.."; 
my $counter = 20; 
local $SIG{ALRM} = sub { 
    say --$counter; 
    alarm 1; 
}; 
alarm 1; 

while ((my $pid = wait) != -1) { 
    say "Child with PID=$pid finished.."; 
} 

alarm 0; 
say "Done."; 

输出:

Waiting for child processes.. 
19 
18 
17 
16 
Child with PID=55240 finished.. 
15 
14 
13 
12 
11 
Child with PID=55239 finished.. 
Done. 
+2

谢谢,这个完美的作品。我使用了'$ SIG {ALRM} = sub {$ counter--;说$ counter;报警1};'它就像一个魅力:) – 2014-08-29 11:09:35