Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, So I have a conceptual question. I am wondering if there's a way that I can distinguish between different childs; is there a child number, like first child, second child etc? What I would like is, each time the parent spawns off a child it would also give the child some distinct number so the different childs can, say, look at different files. For example:
#!/usr/bin/perl @dirname; $dirname[0]="TestList1.log"; $dirname[1]="TestList2.log"; $dirname[2]="TestList3.log"; for(1..4) { my $pid = fork(); if ($pid) { # parent push(@childs, $pid); print "we are in the parent bus \n"; waitpid($pid,0); } elsif ($pid == 0) { # child # here I want to read a different file each child # so child 1 would read dirname[0] # so child 2 would read dirname[1] # so child 3 would read dirname[2] # and they would all do the same thing, # but on different files # something like: #$mm = @child array's element number open (filelist, @dirname[$mm]) || die "couldn't open the file!"; @filename; @filename = <filelist>; print "@filename \n"; sleep 5; exit(0); } else { die "couldn’t fork: $! \n"; } print "LAST IN FOR \n"; } print "AFTER FOR \n";
Thanks a lot! - cartmanofvan

Replies are listed 'Best First'.
Re: fork : distinguish between different child?
by keszler (Priest) on Oct 24, 2011 at 23:49 UTC

    Here's one way. I'm sure others will be along shortly.

    #!/usr/bin/env perl use strict; use warnings; my @dirs = (qw/dir1 dir2 dir3 dir4/); my @kids; for my $i (1..4) { my $pid = fork(); if ($pid) { # parent push @kids, $pid; print "spawned child $pid\n"; } elsif ($pid == 0) { print "I am child $$. \@kids count = $#kids. my dir is $dirs[$#kid +s+1]\n"; sleep 5; exit(0); } else { die "couldn.t fork: $! \n"; } print "end loop $i\n"; } for my $pid (@kids) { print "reaping $pid\n"; waitpid($pid,0); }

    Output:

    I am child 20199. @kids count = -1. my dir is dir1 spawned child 20199 end loop 1 I am child 20200. @kids count = 0. my dir is dir2 spawned child 20200 end loop 2 I am child 20201. @kids count = 1. my dir is dir3 spawned child 20201 end loop 3 I am child 20202. @kids count = 2. my dir is dir4 spawned child 20202 end loop 4 reaping 20199 reaping 20200 reaping 20201 reaping 20202
Re: fork : distinguish between different child?
by ikegami (Patriarch) on Oct 24, 2011 at 23:56 UTC

    First, you should be using use strict; use warnings;.

    You do it the same way as you would if you didn't fork.

    for my $idx (1..4) { ... fork ... say $dirnames[$idx - 1]; ... }

    Of course, 4 is wrong since you only have three directories.

    for my $idx (1..@dirnames) { ... fork ... say $dirnames[$idx - 1]; ... }

    But why start at 1?

    for my $idx (0..$#dirnames) { ... fork ... say $dirnames[$idx]; ... }

    But why numbers at all?

    for my $dirname (@dirnames) { ... fork ... say $dirname; ... }

    Of course, your flow doesn't make much sense right now if you're trying to make stuff parallel.

    1. Launch first child.
    2. Wait for first child to finish.
    3. Launch second child.
    4. Wait for second child to finish.
    5. Launch third child.
    6. Wait for third child to finish.
    7. Launch fourth child.
    8. Wait for fourth child to finish.

    You want:

    1. Launch first child.
    2. Launch second child.
    3. Launch third child.
    4. Launch fourth child.
    5. While children exist,
      1. Wait for a child to finish.

    See also: Parallel::ForkManager

Re: fork : distinguish between different child?
by JavaFan (Canon) on Oct 25, 2011 at 00:43 UTC
    I am wondering if there's a way that I can distinguish between different childs; is there a child number, like first child, second child etc?
    You mean, does the OS assign each process a unique number? It certainly does, the process ID. It's the return value of fork (in the parent).

    But you already knew that, judging from your code.

      How does that help him get the right array element?
Re: fork : distinguish between different child?
by cartmanofvan (Initiate) on Oct 25, 2011 at 19:09 UTC
    Thanks Monks!

    keszler (Deacon) on Oct 24, 2011 at 23:49 UTC, your reply worked perfectly! Thanks a lot - this is exactly what I wanted! PS. there's a little typo in the line print "I am child $$. \@kids count = $#kids. my dir is $dirs[$#kid+s+1]\n"; where the last bit should read [$#kids+1] (sorry I am not being anal here, but just for people who might just copy paste this code, which I sometimes do when I search forums).

    ikegami (Pope) on Oct 24, 2011 at 23:56 UTC, thanks for the 'use' tips; I am new to perl so this helps. But, Deacon's method is not in series, it is in fact in parallel - I just checked by putting a sleep inside childs and also printing the localtime(time) out to the second. So in fact it is launching all childs at the same time.

    JavaFan (Abbot) on Oct 25, 2011 at 00:43 UTC, no I didn't know this, but Deacon's code enlightened me on this.

    ikegami (Pope) on Oct 25, 2011 at 04:45 UTC, the array element is given by [$#childs+1] as Deacon showed.

    Thanks again Monks! (again I didn't mean to unnecessarily lengthen this comment thread by addressing every point, I just thought it would be helpful for people searching the forum)