2014-08-29 102 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