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

Hi, I'm trying to write a SIMPLE script that uses interprocess communication to do the following:

1. Define an empty array called @myarray in the parent process.
2. Fork 3 child processes (for simplicity we'll call them pid1, pid2, and pid3).
3. For each child process, push an integer onto the array: pid1 will push (@myarray, 1), pid2 push (@myarray,2) and pid3 will push (@myarray,3).
4. The end result is that the parent process has @myarray containing (1,2,3).

I'm new to process management and IPC stuff, so I'm just trying to find the simplest way to allow @myarray to be "shared" so all processes have access to modify it. Thank you so much for your help; this site is great!

Replies are listed 'Best First'.
Re: simple IPC
by zentara (Cardinal) on Dec 23, 2004 at 18:17 UTC
    Does it have to be IPC? If so, you need to make a pipe to read from each of the child processes. It would be easiest to use IPC::Open2. Or you can just use a simple piped form of open. Here is a way to do it for just one child, loop it 3 times, for your needs. If you need them simultaneous, put the CHILD filehandles in a hash, and use IO::Select to read them.
    #!/usr/bin/perl use strict; use warnings; my $pid = open(CHILD, "-|"); if ($pid) { # parent print "parent got:\n"; print while(<CHILD>); close CHILD; # this waits on child } elsif ($pid == 0) { # child print "kid here!\n"; exec '/bin/date' or die "Can't exec date $!\n"; } else { die "fork error: $!\n"; }

    I'm not really a human, but I play one on earth. flash japh
Re: simple IPC
by revdiablo (Prior) on Dec 23, 2004 at 19:19 UTC

    Take a look at IPC::Shareable. This seems like a perfect situation to use it. If that doesn't work, look at CPAN's other IPC modules -- there are lots of them.

Re: simple IPC
by saintmike (Vicar) on Dec 23, 2004 at 22:41 UTC
    It's not exactly simple, but here's how to do it the old-fashioned way with pipe, sysread, and syswrite. Note how the pipe protocol uses the number of bytes transferred in every message to detect its length:
    use strict; my @array = (); pipe my $read, my $write or die "Cannot open pipe"; for(1..3) { defined(my $pid = fork) or die "Can't fork\n"; if($pid) { next; # Parent: continue loop } # Child pipe_send($write, "I'm process $$!"); exit 0; } # Parent for(1..3) { my $element = pipe_recv($read); push @array, $element; } print "array = @array\n"; ################################################## sub pipe_send { ################################################## my($fh, $message) = @_; my $bytes = sprintf "0x%08x", length($message); syswrite($fh, $bytes . $message); } ################################################## sub pipe_recv { ################################################## my($fh) = @_; die "Protocol corrupted" if sysread($fh, my $bytes, 10) != 10; $bytes = hex($bytes); my $data = ""; while($bytes != 0) { my $read = sysread($fh, my $chunk, $bytes); last unless defined $read; $bytes -= $read; $data .= $chunk; } return $data; }
      Thank you so much everyone. I got it working now. I needed to figure this out because I'm working on a large complex script that polls the MAC-address table (CAM) of several switches on a large network, then consolidates the results into a database. Knowing how to make the polling processes run simultaneously (using the example above), my code will be much more efficient now instead of polling the switches one at a time. Thanks again, you all rock!
Re: simple IPC
by BrowserUk (Patriarch) on Dec 23, 2004 at 17:52 UTC

    This is trivial using threads.


    Examine what is said, not who speaks.        The end of an era!
    "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
    "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

      I said it was trivial:)

      #! perl -slw use strict; use threads; use threads::shared; my @myarray : shared; sub pid { lock @myarray; push @myarray, $_[ 0 ]; } threads->new( \&pid, $_ )->detach for 1 .. 3; sleep 2; print "@myarray"; __END__ [23:30:52.15] P:\test>417163 1 2 3

      Examine what is said, not who speaks.        The end of an era!
      "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
      "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
      "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon