等待超时的子进程

时间:2014-08-29 10:25:59

标签: perl

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

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;
}

我对这种方法的关注是我为计时器创建了一个分叉的子进程,这似乎有些过分。这是必要的,还是有更简单的方法?

1 个答案:

答案 0 :(得分:4)

查看alarm() - 在指定的超时后触发一个终止信号ALRM。哪个会破坏流程,或者你可以使用:

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

alarm()不会传播到分叉流程,因此您可以在父母的“父母”上进行设置。所以它只是等待孩子的时间。

你可能不需要分叉你的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.