| Article Index |
|---|
| Interprocess Communication (IPC), Pipes |
| Page 2 |
| All Pages |
Interprocess Communication (IPC), Pipes
There is no form of IPC that is simpler than pipes. Implemented on every flavor of Unix, pipe() and fork() make up the functionality behind the "|" in "ls | more". They are marginally useful for cool things, but are a good way to learn about basic methods of IPC. We have now began to see how multiple processes may be running on a machine and maybe be controlled (spawned by fork() by one of our programs.
In numerous applications there is clearly a need for these processes to communicate with each exchanging data or control information. There are a few methods which can accomplish this task. We will consider:
* Pipes
* Signals
* Message Queues
* Semaphores
* Shared Memory
* Sockets
In this chapter, we will study the piping of two processes. We will study the others in turn in subsequent chapters.
Piping in a C program: <stdio.h>
Piping is a process where the input of one process is made the input of another. We have seen examples of this from the UNIX command line using $mid$.
We will now see how we do this from C programs.
We will have two (or more) forked processes and will communicate between them.
We must first open a pipe
UNIX allows two ways of opening a pipe.
popen() -- Formatted Piping
FILE *popen(char *command, char *type) -- opens a pipe for I/O where the command is the process that will be connected to the calling process thus creating the pipe. The type is either ``r'' - for reading, or ``w'' for writing.
popen() returns is a stream pointer or NULL for any errors.
A pipe opened by popen() should always be closed by pclose(FILE *stream).
We use fprintf() and fscanf() to communicate with the pipe's stream.
pipe() -- Low level Piping
int pipe(int fd[2]) -- creates a pipe and returns two file descriptors, fd[0], fd[1]. fd[0] is opened for reading, fd[1] for writing.
pipe() returns 0 on success, -1 on failure and sets errno accordingly.
The standard programming model is that after the pipe has been set up, two (or more) cooperative processes will be created by a fork and data will be passed using read() and write().
Pipes opened with pipe() should be closed with close(int fd).
Example: Parent writes to a child
int pdes[2];
pipe(pdes);
if ( fork() == 0 )
{ /* child */
close(pdes[1]); /* not required */
read( pdes[0]); /* read from parent */
.....
}
else
{ close(pdes[0]); /* not required */
write( pdes[1]); /* write to child */
.....
}
An futher example of piping in a C program is plot.c and subroutines and it performs as follows:
* The program has two modules plot.c (main) and plotter.c.
* The program relies on you having installed the freely gnuplot graph drawing program in the directory /usr/local/bin/ (in the listing below at least) -- this path could easily be changed.
* The program plot.c calls gnuplot
* Two Data Stream is generated from Plot
o y = sin(x)
o y = sin(1/x)
* 2 Pipes created -- 1 per Data Stream.
* °Gnuplot produces ``live'' drawing of output.




