[Refresher] Pipes and FIFO Special Files (in POSIX)

Use pipes (nameless/unnamed) and FIFO files (named pipes) in POSIX.

Pipes

To create a pipe:

#include <unistd.h>
int pipe(int filedes[2]);
  • pipe() opens filedes[0] for reading and filedes[1] for writing. It returns 0 if OK, -1 on error with errno set appropriately.
    • Visually: <-- read() <-- [0] <-- pipe <-- [1] <-- write() <--
  • The descriptors can be read()-ed, write()-ed, and should be closed()-ed.

Sample code using pipes for parent-child communication:

  // Create pipes
  int fd_p2c[2], fd_c2p[2];
  if (pipe(fd_p2c) < 0) {
    // Error
  }
  if (pipe(fd_c2p) < 0) {
    // Error
    close(fd_p2c[0]);
    close(fd_p2c[1]);
  }

  pid_t child_pid;
  child_pid = fork();
  if (child_pid == 0) {
    // Child
    close(fd_p2c[1]);  // Don't need to write
    close(fd_c2p[0]);  // Don't need to read

    int fd_p2c = fd_p2c[0];
    int fd_c2p = fd_c2p[1];
    // Process something...
    //   read(fd_p2c[0], ...)
    //   write(fd_c2p[1], ...)

    close(fd_p2c[0]);
    close(fd_c2p[1]);
  }
  else if (child_pid > 0) {
    // Parent process
    close(fd_p2c[0]);  // Don't need to read
    close(fd_c2p[1]);  // Don't need to write

    // Process something...
    //   read(fd_c2p[0], ...)
    //   write(fd_p2c[1], ...)

    close(fd_p2c[1]);
    close(fd_c2p[0]);
  }
  else {
    // Error
    close(fd_p2c[0]);
    close(fd_p2c[1]);
    close(fd_c2p[0]);
    close(fd_c2p[1]);
  }

FIFO Special Files

To create a FIFO special file (a named pipe):

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
  • mkfifo() creates a FIFO but does not open() it. It returns 0 if OK, -1 on error with errno set appropriately.
  • A typical value for mode: (mode_t) (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH).
  • Can use unlink() to remove a FIFO file.
  • A few combinations in opening the FIFO file:
    • O_RDONLY and O_WRONLY: Sometimes used for process synchronization.
    • O_RDONLY and O_WRONLY | O_NONBLOCK: If not open it for reading yet, opening it for writing results in a failed open() with errno set to ENXIO.
    • O_RDONLY | O_NONBLOCK and O_WRONLY: Useful for initiating a single report process and multiple reader processes.
    • O_RDONLY | O_NONBLOCK and O_WRONLY | O_NONBLOCK: Avoid this as result is unspecified.

Miscellaneous

  • Any write() to a pipe or FIFO of PIPE_BUF or fewer bytes will be atomic.
  • PIPE_BUF is available from limits.h when _POSIX_SOURCE has been defined. It is at least _POSIX_PIPE_BUF == 512.