Differences between revisions 1 and 4 (spanning 3 versions)
Revision 1 as of 2007-05-02 23:14:52
Size: 2296
Editor: redondos
Comment:
Revision 4 as of 2009-03-25 12:38:25
Size: 2302
Editor: GreyCat
Comment: clean up a bit
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
[[Anchor(faq27)]]
== How can two processes communicate using named pipes (fifos)? ==
NamedPipes, also known as FIFOs ("First In First Out") are well suited for inter-process communication. The advantage over using files as a means of communication is, that processes are synchronized by pipes: a process writing to a pipe blocks if there is no reader, and a process reading from a pipe blocks if there is no writer.
<<Anchor(faq27)>>
== How can two unrelated processes communicate? ==
Two unrelated processes cannot use the arguments, the environment or
stdin/stdout to communicate; some form of inter-process communication (IPC)
is required.
Line 5: Line 7:
Here is a small example of a server process communicating with a client process. The server sends commands to the client, and the client acknowledges each command: === A file ===
  
Process A writes in a file, and Process B reads the file. This method is not synchronized and therefore is not
safe if B can read the file while A writes in it. A lockdir or a
signal can probably help
Line 7: Line 13:
'''Server''' === A directory as a lock ===

`mkdir` can be used to test for the existence of a dir and create it in one
atomic operation; it thus can be used as a lock, although not a very
efficient one.

Script A:
Line 9: Line 21:
#! /bin/sh
# server - communication example

# Create a FIFO. Some systems don't have a "mkfifo" command, but use
# "mknod pipe p" instead

mkfifo pipe

while sleep 1
do
    echo "server: sending GO to client"

    # The following command will cause this process to block (wait)
    # until another process reads from the pipe
    echo GO > pipe

    # A client read the string! Now wait for its answer. The "read"
    # command again will block until the client wrote something
    read answer < pipe

    # The client answered!
    echo "server: got answer: $answer"
done
    until mkdir /tmp/dir;do # wait until we can create the dir
      sleep 1
    done
    echo foo > file # write in the file this section is critical
    rmdir /tmp/dir # remove the lock
Line 34: Line 28:
'''Client'''
{{{
#! /bin/sh
# client

# We cannot start working until the server has created the pipe...
until [ -p pipe ]
do
    sleep 1; # wait for server to create pipe
done

# Now communicate...

while sleep 1
do
    echo "client: waiting for data"

    # Wait until the server sends us one line of data:
    read data < pipe

    # Received one line!
    echo "client: read <$data>, answering"

    # Now acknowledge that we got the data. This command
    # again will block until the server read it.
    echo ACK > pipe
done
Script B:
{{{
    until mkdir /tmp/dir;do #wait until we can create the dir
      sleep 1
    done
    read var < file # read in the file this section is, critical
    echo "$var" # Script A cannot write in the file
    rmdir /tmp/dir # remove the lock
  
Line 63: Line 39:
Write both examples to files {{{server}}} and {{{client}}} respectively, and start them concurrently to see it working: See [[http://mywiki.wooledge.org/BashFAQ/045|Faq #45 ]] and
[[[http://www.bash-hackers.org/wiki/doku.php/howto/mutex | mutex]]
for more examples with a lock directory.
Line 65: Line 43:

=== Signals ===

Signals are probably the simplest form of IPC:
  
ScriptA:
Line 66: Line 50:
    $ chmod +x server client
    $ server & client &
    server: sending GO to client
    client: waiting for data
    client: read <GO>, answering
    server: got answer: ACK
    server: sending GO to client
    client: waiting for data
    client: read <GO>, answering
    server: got answer: ACK
    server: sending GO to client
    client: waiting for data
    [...]
    trap 'flag=go' USR1 #set up the signal handler for the USR1 signal

    # echo $$ > /tmp/ScriptA.pid #if we want to save the pid in a file

    flag=""
    while [[ $flag != go ]]; do # wait for the green light from Script B
      sleep 1;
    done
    echo we received the signal
Line 80: Line 60:

You must find or know the pid of the other script to send it a
signal using kill:
{{{
     #kill all the
     pkill -USR1 -f ScriptA
     
     #if ScriptA saved its pid in a file
     kill -USR1 $(</var/run/ScriptA.pid)

     #if ScriptA is a child:
     ScriptA & pid=$!
     kill -USR1 $pid
}}}

The first 2 methods are not bullet proof and will cause trouble if
you run more than one instance of scriptA.

=== Named Pipes ===

Named pipes are a much richer form of IPC. They are described on their
own page: NamedPipes.

How can two unrelated processes communicate?

Two unrelated processes cannot use the arguments, the environment or stdin/stdout to communicate; some form of inter-process communication (IPC) is required.

A file

Process A writes in a file, and Process B reads the file. This method is not synchronized and therefore is not safe if B can read the file while A writes in it. A lockdir or a signal can probably help

A directory as a lock

mkdir can be used to test for the existence of a dir and create it in one atomic operation; it thus can be used as a lock, although not a very efficient one.

Script A:

    until mkdir /tmp/dir;do # wait until we can create the dir
      sleep 1
    done
    echo foo > file         # write in the file this section is critical
    rmdir /tmp/dir          # remove the lock

Script B:

    until mkdir /tmp/dir;do #wait until we can create the dir
      sleep 1
    done
    read var < file         # read in the file this section is, critical
    echo "$var"             # Script A cannot write in the file
    rmdir /tmp/dir          # remove the lock

See Faq #45 and mutex for more examples with a lock directory.

Signals

Signals are probably the simplest form of IPC:

ScriptA:

    trap 'flag=go' USR1 #set up the signal handler for the USR1 signal

    # echo $$ > /tmp/ScriptA.pid #if we want to save the pid in a file

    flag=""
    while [[ $flag != go ]]; do # wait for the green light from Script B
      sleep 1;
    done
    echo we received the signal

You must find or know the pid of the other script to send it a signal using kill:

     #kill all the
     pkill -USR1 -f ScriptA 
     
     #if ScriptA saved its pid in a file
     kill -USR1 $(</var/run/ScriptA.pid)

     #if ScriptA is a child:
     ScriptA & pid=$!
     kill -USR1 $pid

The first 2 methods are not bullet proof and will cause trouble if you run more than one instance of scriptA.

Named Pipes

Named pipes are a much richer form of IPC. They are described on their own page: NamedPipes.

BashFAQ/027 (last edited 2010-05-11 05:25:30 by p5B09615D)