- Forward


Pipes
and FIFOs


Prof. David Bernstein
James Madison University

Computer Science Department
bernstdh@jmu.edu

Print

Review
Back SMYC Forward
  • Process:
    • An instance of a program execution
  • Interprocess Communication:
    • Processes can communicate with each other in a variety of different ways
    • Pipes and FIFOs are examples of IPC mechanisms
Background:
Back SMYC Forward
  • Using the File System:
    • Processes can use the file system to share information (e.g., one can write to a file and another can read from the file) but it is slow
  • Some History:
    • People often used to use "RAM disks" to make the process faster
  • The Motivation for Pipes/FIFOs:
    • Why not use memory more directly
Characteristics of Pipes/FIFOs
Back SMYC Forward
  • Byte Streams:
    • As with files, they involve an undelimited byte stream
  • Unidirectional:
    • One end is used for writing and the other end is used for reading
  • Destructive Reads:
    • The reader removes bytes from the stream (i.e., buffer)
Characteristics of Pipes/FIFOs (cont.)
Back SMYC Forward
  • Limited Capacity:
    • Since a pipe/FIFO is a buffer in kernel memory it has a limited capacity
  • Atomic Writes:
    • Writes (of up to PIP_BUF bytes) are guaranteed to be atomic (hence, if multiple processes are writing to the same pipe/FIFO their bytes won't be "intermingled")
  • Blocking:
    • When a pipe/FIFO is "full" (i.e., if there is not enough space for the write), a write will block until enough bytes have been read
    • When a pipe/FIFO is empty, a read will block until at least one byte has been written (or the write end has been closed)
Pipes vs. FIFOs
Back SMYC Forward
  • Pipes:
    • Use file descriptors (hence can only be used by processes that can "share" file descriptors)
    • When the pipe is created, two file descriptors are created (one for the read end and one for the write end)
    • If the reading process doesn't close the write end of a pipe then it will not see an EOF after the writing process closes its end (because the kernel knows there is an open write end)
    • The writing process must close the read end so that when a process tries to write to a pipe that has no read end it can be sent a SIGPIPE signal
  • FIFOs:
    • Created using a name within the file system (hence can be used by unrelated processes)
    • The FIFO is created first and then the file descriptors are created by opening the name
Usage
Back SMYC Forward
  • Common Usage:
    • One process writes and another reads
    • Multiple processes write and one other process reads
  • Uncommon Usage:
    • One process reads and writes - there are usually better ways to achieve the same result
    • One or more processes write and multiple other processes read - the order of the reads is unknown
Using C Standard I/O
Back SMYC Forward
  • Associating a FILE*:
    • As with other files, fdopen() fdopen can be used to associate a FILE* with a valid file descriptor
  • Buffering:
    • Output is often written only when the stdio buffer is full (in which case the reader will not receive the bytes immediately) hence one may need to call fflush() fflush
Creating a Pipe: pipe() pipe
Back SMYC Forward
int pipe(int fd[2])
Purpose:
Create a pipe
Details:
fd An outbound array of valid file descriptors (where fd[0] is the read end and fd[1] is the write end)
Return 0 on success; -1 on error
#include <unistd.h> unistd.h
A Simple Example of a Pipe
Back SMYC Forward
unixexamples/pipes/simple.c
 
A More Complicated Example of a Pipe
Back SMYC Forward
unixexamples/pipes/gpa.c
 
Creating a FIFO: mkfifo() mkfifo
Back SMYC Forward
int mkfifo(const char *name, mode_t mode)
Purpose:
Create a FIFO (i.e., a "named pipe")
Details:
name the pathname of the FIFO
mode the permissions (as on files)
Return 0 on success; -1 on error
#include <sys/stat.h> sys/stat.h

Since you need to have at least one writing process on one end and one writing process on the other, by default a call to open() one end (e.g., O_WRONLY will block until another process calls open() for the other end (e.g., O_RDONLY). This behavior can be modified with the O_NONBLOCK flag (though there are many details to consider).

Unlinking a FIFO: unlink() unlink
Back SMYC Forward
int unlink(const char *name)
Purpose:
Remove a link and, if it is the last link to the file, the file itself
Details:
name the pathname of the FIFO
Return 0 on success; -1 on error
#include <unistd.h> unistd.h

Note: There is nothing FIFO-specific about unlink().

Persistence of FIFOs
Back SMYC Forward
  • Remember:
    • FIFOs have process persistence (so it remains in existence as long as one process has it open)
  • Implications:
    • You MUST remember to unlink FIFOs
  • Getting a List of FIFOs:
    • Depending on your naming conventions you may need to use ls -A
An Example of a FIFO - The Reader
Back SMYC Forward
unixexamples/pipes/averager.c
 
An Example of a FIFO - The Writer
Back SMYC Forward
unixexamples/pipes/splitter.c
 
Using Pipes/FIFOs as a Synchronization Mechanism
Back SMYC Forward
  • Pipes:
    1. Parent builds a pipe
    2. Parent constructs a child process (which "inherits" the file descriptors for the pipe)
    3. The "receiving party" reads from the pipe (and, hence, blocks) when it wants to be "notified"
    4. The "sending party" closes the write-end to when it wants to "notify"
  • FIFOs:
    • Can also make use of the fact that (by default) the calls to open() will block until both ends are open.
An Example of Sequencing with a FIFO
Back SMYC Forward
unixexamples/pipes/sequencef.c
 
An Example of Sequencing with a Pipe
Back SMYC Forward
unixexamples/pipes/sequence.c
 
An Example of "Alerting" with a Pipe
Back SMYC Forward
unixexamples/pipes/taxp1.c
 

Note: The "sender" transmits one bit of information (as in the similar example that used signals) by either writing or not. This approach is more subtle than necessary since the pipe can be used to transmit information more directly.

A Less Subtle Example of "Alerting" with a Pipe
Back SMYC Forward
unixexamples/pipes/taxp2.c
 
Using Pipes/FIFOs for Rendezvous Problems
Back SMYC Forward
  • Recall:
    • There are two parties, Andrea and Bill, each of whom performs two tasks in order, \((A1, A2)\) for Andrea and \((B1, B2)\) for Bill
    • The protocol must ensure that \(A1\) happens before \(B2\) and \(B1\) happens before \(A2\)
  • Using Pipes/FIFOs:
    • Use one pipe/FIFO for each sequencing that must be ensured
An Example Rendezvous Protocol
Back SMYC Forward
unixexamples/pipes/rendezvous.c
 
A "Too Strict" Rendezvous Protocol
Back SMYC Forward
unixexamples/pipes/rendezvous_toostrict.c
 

Note: With this protocol B1 will always be completed before A1 (which is not required).

There's Always More to Learn
Back -