Pipes
Pipes are used to allow one or more processes to have information "flow" between them. The most common example of this is with the shell.

$ ls | wc -l
As we’ve seen the std-out from the left side (ls) is connected to the std-in on the right side (wc -l).As far the each program is concerned, it is reading or writing as it normally does. Both processes are running concurrently.

There are 2 types of pipes:
unnamed pipes
named pipes

The examples we seen at the shell command line are unnamed. They are created, used and destroyed within the life a set of processes. Each end of the pipe has it’s own file descriptor. One end is for reading and one end is for writing. When you are done with a pipe, it is closed like any other file.

Creating unnamed pipes

#include <unistd.h>

int pipe(int fd[2]);
Returns 2 file descriptors in the fd array.

fd[0] is for read

fd[1] write

Returns 0 on successful creation of pipe, 1 otherwise.

Each end of the pipe is closed individually using normal close() system call. Pipes are only available the process that creates the pipe and it’s descendants.

Reading from pipes

When reading from a pipe:
read() will return 0 (end of file) when the write end of the pipe is closed. if write end of the is still open and there is no data, read() will block until input become available. if a read() tries to get more data than is currently in pipe, read() will only contain the number of bytes actually read. Subsequent reads will block until more data are available.

Writing to pipes
When writing to a pipe:
If read end of pipe is closes, a write() will fail and process will be sent SIGPIPE signal. Default SIGPIPE handler terminates.


Pipe Example (Unnamed Pipe)
#include <stdio.h>

/* The index of the "read" end of the pipe */
#define READ 0

/* The index of the "write" end of the pipe */
#define WRITE 1

char *phrase = "Stuff this in your pipe and smoke it";

main () {
  int fd[2], bytesRead;

  char message [100]; /* Parent process message buffer */

  pipe ( fd ); /*Create an unnamed pipe*/
  
  if ( fork ( ) == 0 ) {
    /* Child Writer */
    close (fd[READ]); /* Close unused end*/
    write (fd[WRITE], phrase, strlen ( phrase) +1); /* include NULL*/
    close (fd[WRITE]); /* Close used end*/
    printf("Child:  Wrote '%s' to pipe!\n", phrase);

  } else {

    /* Parent Reader */
    close (fd[WRITE]); /* Close unused end*/
    bytesRead = read ( fd[READ], message, 100);
    printf ( "Parent: Read %d bytes from pipe: %s\n", bytesRead, message);
    close ( fd[READ]); /* Close used end */
  } 
}

Named pipes
Named pipes are also FIFO’s (first in first out). They have "names" and exist as special files within a file system. (file type p) They exist until they are removed with rm or unlink() They can be used with unrelated process not just descendants of the pipe creator.

Created with:

mknod utility

mknod() system call

Creating named pipes

From the shell
$ mknod mypipe p
From a C program
mknod ( "mypipe", SIFIFO, 0 );
Either way you create it, this will result in a special file being created on the filesystem.
$ ls -l mypipe
prw-r—r-- 1 srs users 0 Nov 6 22:28 mypipe
Once a named pipe is created, processes can open(), read() and write() them just like any other file. Unless you specify O_NONBLOCK, or O_NDELAY, on the open:
opens for reading will block until a process opens if for writing.

opens for writing will block until a process opens it for reading.

If you DO specify O_NONBLOCK, or O_NDELAY, on the open: Opens for reading will succeed, even there are no processes with it opened for writing. Opens for writing will fail if there are not processes with it opened for reading.

Named Pipe Example

Writer
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

char * phrase = "Stuff this in your pipe and smoke it";

int main () {
  int fd1; 
  fd1 = open ( "mypipe", O_WRONLY ); 
  write (fd1, phrase, strlen ( phrase)+1 ); 
  close (fd1);
}

Reader

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main () {
  int fd1;
  char buf [100];

  fd1 = open ( "mypipe", O_RDONLY ); 
  read ( fd1, buf, 100 ); 
  printf ( "%s\n", buf ); 
  close (fd1);
} 


NOTE 1: This document was snarfed and reformatted from http://www.cs.fredonia.edu/~zubairi/s2k2/csit431/pipes.html. Sample code was slightly improved. — fgm

NOTE 2: This help document was taken from academic website and it also contains example source code from a UNIX programming book