Interprocess Communication

bulletInterprocess communication concepts
bulletDifferent processes do not share address space -- they need interprocess communication to talk to one another.
bulletThis is not network programming, where processes running on different machines talk to each other via network. Here all the processes involved are running on the same machine.
bulletThe processes having parent-child relation can communicate with global variables. After the termination of the child the parent can receive values from the children by their exit code.
bulletIn this lecture we will consider pipe and FIFO, which are part of POSIX, and are supported by many UNIX implementation.
bulletPipe
bulletPipe is a half-duplex communication channel between processes that have parent-child relation.
bulletThe pipe interface opens a pipe for reading at one end, and writing at the other.
bulletIt is easy to see that other than parent-child related processes, others could not know the file descriptors, and cannot use them as a result.
bulletAfter creating a pipe a process usually creates another copy by fork, so that they share the pipe. Usually the parent and the child will decide whether to read from or write to the pipe, and will close the other end that they do not need.
bulletSee the figure on page 430 for an illustration.
bulletThere could be all kinds of problem accessing a pipe.
bulletRead from a closed pipe.
bulletThe read returns 0, just like an EOF.
bulletWrite to a closed pipe.
bulletA SIGPIPE is generated.
bulletNow try the program on page 431.
bulletThe parent writes and the child reads.
bulletNow consider a program that pipes the output to a pager (on page 432).
bulletThe default pager is "more".
bulletThe parent does the following:
bulletThe parent creates a pipe and share it with the child.
bulletThen the parent reads from a file, and writes to the pipe. The parent repeats this process until it reads all the data from the input file.
bulletThen the parent waits for the child to complete.
bulletThe child does the following:
bulletThe child direct its standard input to the input end of the pipe (with dup).
bulletThen the child determines the pager -- it is either from the environment or from the default value.
bulletThen the child exec the pager. Since the standard input has been redirected to the pipe. The pager will read from the pipe.
bulletNow we use pipe to synchronize parent and child (the code is on page 434).
bulletThe code has three major groups of functions.
bulletTELL_WAIT
bulletThe subroutine creates two pipes -- one for letting the parent wait for the child, and one for the other way around
bulletTELL_PARENT and TELL_CHILD
bulletThese routines tell the other by writing a string into the pipe.
bulletWAIT_PARENT and WAIT_CHILD
bulletThese routines try to read from the pipe. If the data is not there, they will block -- just as we want them to.
bulletpopen and pclose interface
bulletThe popen interface integrates the following into a single function.
bulletCreate a pipe.
bulletFork a child process.
bulletMake the child process exec a command.
bulletThe arguments to popen.
bulletA command string
bulletWhat do you want the child to do?
bulletA "direction string"
bulletThe parent should read from ("r") or write to ("w") the pipe.
bulletThe same pager program is implemented with popen in a simpler way on page 436.
bulletThe implementation of popen on page 438-439.
bulletThe implementation uses an array of process ids to record those process ids that are associated with a particular pipe file descriptor. The pipe file descriptor is used to index this array. See below.
bulletThe parent does the following.
bulletCreates a pipe.
bulletForks a child process.
bulletUse fdopen to convert the file descriptors (int) returned by pipe into standard I/O style file pointer (FILE*).
bulletThe file pointer is returned.
bulletThe child does the following.
bulletDepending on the direction string, redirects the standard input (output) to the reading (writing) end of the pipe.
bulletExecutes the command string.
bulletThe pclose does the following.
bulletUses fileno to convert a file pointer back to a file descriptor.
bulletUses the file descriptor as an index to access the child process id stored during popen.
bulletUses waitpid to wait until the child ends.
bulletReturns the status code from the child.
bulletWe can use popen to filter the input we want to send into an application.
bulletFirst check out the filter program on page 440, which reads in characters and convert them into lower case.
bulletThe program flushes the output when it sees a newline, and terminates when the input is EOF.
bulletThe main program uses popen to create a process and make it run the filter program.
bulletThen the main program writes the prompt.
bulletThe child filter process reads from the stdin and convert it into lower case.
bulletThe child filter process then writes the output into the pipe, which will be read by the parent.
bulletCoprocess
bulletA filter reads from stdin, and writes to stdout.
bulletA coprocess is a process that reads and writes data to another process.
bulletSee the picture on page 441 for an example.
bulletProgram 14.8 is a filter that reads two data from stdin, adds them together, and writes the result to stdout. We compile it and name it add2.
bulletNow we write another program that creates a coprocess running add2.
bulletFirst the program installs a signal handler for SIGPIPE, which will be generated if there is something wrong with the pipe,
bulletThen the program creates two pipes and forks a child process.
bulletThe parent does the following:
bulletCloses those fds it does not need.
bulletReads two numbers from stdin, and writes to the first pipe.
bulletReads from the second pipe, which should have the sum of the two numbers written in to the first pipe.
bulletWrites the result to stdout.
bulletThe child does the following:
bulletCloses those fds it does not need.
bulletRedirects the stdin to the input end of the pipe, and stdout to the output end of the pipe,
bulletexec add2.
bulletFIFO
bulletA FIFO is a named pipe, that is, a pipe with a name in the file system.
bulletFIFO is a special kind of file. In fact it is simply a place where different processes (not necessarily have parent-child relation) can communicate.
bulletA FIFO is created by mkfifo system call, which is quite similar to open.
bulletWhen accessing a FIFO, implicit synchronization is in effects.
bulletThe reading process will block in the open call until some other process open it for writing.
bulletIf O_NONBLOCK is specified, the open for reading returns immediately, but the open for write-only will have runtime error.
bulletA writing process will have SIGPIPE if no one open the FIFO for reading.
bulletFIFO usage
bulletPassing data between one shell command to another.
bulletSee the example on page 446.
bulletA FIFO fifo1 is created just to route data.
bulletA command tee is used to duplicate data into two direction.
bulletClient-server communication
bulletTwo processes can communicate via a well-known FIFO.
bulletFigure 14.12 shows that different clients can send messages to the same server, however, the server will not be able to reply since we cannot be sure that the correct client will read the correct message.
bulletThe solution is in Figure 14.13, where each client has its own FIFO to which the server can send reply.