My program will fork, launching $n children. When a child finishes, the parent will launch a new one, if we have more to launch.
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ":sys_wait_h";
#function, that every child will run
sub func
# {{{
{
my $i = shift;
my $delay = shift;
print "$i started\n";
sleep($delay);
print "$i finished\n";
}
# }}}
#max number of concurrent children
my $max_n = 2;
#number of seconds each child will sleep
my @delays = (8, 5, 5);
my $n_elements = scalar(@delays);
#number of currently running children
my $n;
if ($n_elements > $max_n) {
$n = $max_n;
}
else {
$n = $n_elements;
}
#initial children creation
my $i;
for ($i = 0; $i < $n; $i++) {
my $pid = fork();
if ($pid == 0) {
#child runs the function
func($i, $delays[$i]);
exit(0);
}
}
#any children still running?
while ($n > 0) {
#wait until one of them dies
my $dead_child_pid = wait();
print "$dead_child_pid done\n";
#do we need to create new children?
if ($i < $n_elements) {
#create a child
my $pid = fork();
if ($pid == 0) {
func($i, $delays[$i]);
exit(0);
}
else {
#move pointer to the next element of @delays
++$i;
}
}
else {
#decrease number of running children
$n--;
}
}
print "parent finished\n";
When I run it, it prints:
1 started
0 started
Here I check the processes:
bash-4.2$ ps -A | grep perl
3433 pts/2 00:00:00 perl
3434 pts/2 00:00:00 perl
3435 pts/2 00:00:00 perl
So, it created 3 processes: 3433 - parent, 3434 and 3435 - children. Then:
1 finished
3435 done
2 started
Now again:
bash-4.2$ ps -A | grep perl
3433 pts/2 00:00:00 perl
3434 pts/2 00:00:00 perl
3438 pts/2 00:00:00 perl
It launched the 3-rd child with pid 3438 after the death of the 2-nd.
0 finished
3434 done
2 finished
3438 done
parent finished
So, everything seems to be correct with the exception of the reversed launching order of children in the 1-st loop.
Maybe, it's possible to unite children creation from the both loops into a function. As their code has similar parts:
my $pid = fork();
if ($pid == 0) {
#child runs the function
func($i, $delays[$i]);
exit(0);
}
Do you see any more drawbacks in my code?