Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Concurrency : FORK and knife

by jsl (Initiate)
on Jun 15, 2001 at 20:58 UTC ( [id://88852]=perlquestion: print w/replies, xml ) Need Help??

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

Dear Monks. By the way, is Monks short for Monkeys?
Today's question is ...
I would like to know how the multiprocessing works, when used in Perl function, FORK().
I tried doing this ... written in pseudo-code
--START-- OPEN FILE TO READ AND WRITE; IF ($PID = FORK()) { SLEEP(1); WRITE 'ALPHA'; SLEEP(5); WRITE 'BETA'; } ELSE (DEFINED $PID) { SLEEP(3); READ THE FILE; #Hope to output 'ALPHA' SLEEP(7); READ THE FILE; #Hope to output 'ALPHA' and 'BETA' } CLOSE THE FREAKING FILE; --DONE--
What I want to do is,
let the parent write at SLEEP(1) and
let the child read at SLEEP(3) output : 'ALPHA' and
let the parent write at SLEEP(5) and
let the child read at SLEEP(7) output : 'ALPHA' 'BETA'.
But of course, thank Perl God, it doesn't work.
But what does work is ...
--START-- IF ($PID = FORK()) { SLEEP(1); open file; WRITE 'ALPHA'; close file; SLEEP(5); open file; WRITE 'BETA'; close file; } ELSE (DEFINED $PID) { SLEEP(3); open file; READ THE FILE; close file; SLEEP(7); open file; READ THE FILE; close file; } --DONE--
In this program, it opens and closes every time you want to read or write to a file.
So it seems that given one FILE, two processes cannot access the FILE at the same time.
My 'theory' correct?
Any better idea than this continual opening and closing file when reading and writing to a file?

G'day
jsl

Replies are listed 'Best First'.
Re: Concurrency : FORK and knife
by enoch (Chaplain) on Jun 15, 2001 at 22:20 UTC
    This may be an overkill, but why not use semaphores? In pseudo-code:
    $SEM = CREATE SEMAPHORE; IF ($PID == FORK()) { wait($SEM); # grab the semaphore open file; WRITE 'ALPHA'; close file; signal($SEM); # signal semaphore wait($SEM); # wait for signal from child open file; WRITE 'BETA'; close file; signal($SEM); # signal semaphore } ELSE IF(DEFINED $PID) { SLEEP(3); # make sure parent grabs semaphore wait($SEM); # wait for signal from parent open file; READ THE FILE; close file; signal($SEM); # done with file ops, signal semaphore wait($SEM); # wait for signal from parent that it is done writing +to file open file; READ THE FILE; close file; signal($SEM); }
    In Perl, I would recommend using IPC::SysV. It seems better suited than just the Perl primitives. Here's a quick little Perl blurb (warning: untested).
    use IPC::SysV qw(IPC_PRIVATE S_IRWXU IPC_CREAT); use IPC::Semaphore; my $sem = new IPC::Semaphore(IPC_PRIVATE, 1, S_IRWXU | IPC_CREAT); $sem->setall( (0) x 10); my $semid = $sem->getVal($sem); if(my $pid = fork()) { $sem->op($semid, -1, IPC_NOWAIT); #get the semaphore open(FILE, ">/myFile.txt") or die "error: $!\n"; print FILE "Hello, my name is Perl.\n"; close FILE; $sem->op($semid, 1, IPC_NOWAIT); # signal semaphore $sem->op($semid, -1, IPC_NOWAIT); #wait on semaphore open(FILE, ">/myFile.txt") or die "error: $!\n"; print FILE "Hello, again, my child.\n"; close FILE; $sem->op($semid, 1, IPC_NOWAIT); # signal semaphore } elsif(defined $pid) { sleep(3); $sem->op($semid, -1, IPC_NOWAIT); #wait on semaphore open(FILE, "/myFile.txt") or die "error: $!\n"; print while(<FILE>); close FILE; $sem->op($semid, 1, IPC_NOWAIT); # signal semaphore $sem->op($semid, -1, IPC_NOWAIT); #wait on semaphore open(FILE, "/myFile.txt") or die "error: $!\n"; print while(<FILE>); close FILE; $sem->op($semid, 1, IPC_NOWAIT); exit(0); #exit child } $sem->remove;
    Of course, that, again, might be an overkill. You could probably accomplish it with some extra file foo or so.

    Jeremy
Re: Concurrency : FORK and knife
by nardo (Friar) on Jun 15, 2001 at 22:30 UTC
    The data from your writes isn't being flushed to disk.
    use FileHandle; use strict; my $data; my $pid; open(FILE, '+>outfile'); FILE->autoflush(1); if(($pid = fork())) { sleep(1); print FILE 'ALPHA'; sleep(5); print FILE 'BETA'; wait(); } else { sleep(3); seek(FILE, 0, 0); read(FILE, $data, (stat(FILE))[7]); print $data, "\n"; sleep(7); seek(FILE, 0, 0); read(FILE, $data, (stat(FILE))[7]); print $data, "\n"; } close(FILE);


    will output:

    ALPHA
    ALPHABETA

    which I think is what you want.
Re: Concurrency : FORK and knife
by mothra (Hermit) on Jun 15, 2001 at 22:22 UTC
    There is no FORK() function in Perl. Perhaps you meant fork()?

    Also, your attitude is patronizing ("is Monks short for Monkeys?", "Today's question is ..."), and your post poorly formatted.

    Consider lurking for a little while longer to see how things work around The Monastary before you post again.

Re: Concurrency : FORK and knife
by jwest (Friar) on Jun 15, 2001 at 22:25 UTC
    Well, to sort of answer one of your questions- after writing, you need to go back to the begining of the file to read it. The cursor (more or less) is left just after where you finished writing. Set the cursor to the beginning of the file again with a seek(FILEHANDLE, 0, 0).

    Then, after a read, you'll be ready at the end of the file for the next write. So goes the theory...
    Your unpredictable results will be closer to what you expect. Sort of.

    Probably you shouldn't be doing this, though.

    -><- -><- -><- -><- -><-
    All things are Perfect
        To every last Flaw
        And bound in accord
             With Eris's Law
     - HBT; The Book of Advice, 1:7
    
Re: Concurrency : FORK and knife
by petral (Curate) on Jun 15, 2001 at 22:23 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://88852]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (3)
As of 2024-03-29 05:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found