TLPI - Chapter 44
Pipe and Fifos
Shu-Yu Fu (shuyufu at gmail.com)
Pipes
● Pipes can be used to pass data between
related processes.
$ ls | wc -l
Important Characteristics of Pipes
● A pipe is a byte stream
● Reading from a pipe
● Pipes are unidirectional
● Writes of up to PIPE_BUF bytes are
guaranteed to be atomic
○ using fpathconf(fd, _PC_PIPE_BUF) to return the
actual upper limit
● Pipes have a limited capacity
○ using fcntl(fd, F_SETPIPE_SZ, size) to change the
capacity of the pipe referred to by fd
○ using fcntl(fd, F_GETPIPE_SZ) to get the capacity of
the pipe referred to by fd
Creating and Using Pipes
#include <unistd.h>
int pipe(int filedes[2]);
Creating and Using Pipes (cont.)
● We can also use the stdio functions (printf(),
scanf(), and so on) with pipes by first using
fdopen() to obtain a file stream corresponding
to one of the descriptors in fieldes.
○ Using ioctl(fd, FIONREAD, &cnt) to get the number of
unread bytes in the pipe referred to by fd
A pipe has few uses within a single
process
A pipe has few uses within a single
process (cont.)
● If we require bidirectional communication,
there is a simpler way: just create two pipes,
one for sending data in each direction
between the two processes.
○ deadlocks may occur if both processes block while
trying to read from empty pipes or while trying to
write to pipes that are already full
Closing unused pipe file descriptors
● Ensuring a process doesn't exhaust its limited set of file
descriptors.
● It is only after all file descriptors in all processes that refer to
a pipe are closed that the pipe is destroyed.
Pipes as a Method of Process
Synchronization
● Listing 44-3: Using a pipe to synchronize
multiple processes
● It can be used to coordinate the actions of
one process with multiple other (related)
processes.
● The fact that multiple (standard) signals can't
be queued makes signals unsuitable in this
case. But signals can be broadcasted by one
process to all of the members of a process
group.
Using Pipes to Connect Filters
● Listing 44-4: Using a pipe to connect ls and
wc
● dup2() allows us to explicitly specify the
descriptor to be bound
int pfd[2];
pipe(pfd);
if (pfd[1] != STDOUT_FILENO) {
dup2(pfd[1], STDOUT_FILENO);
close(pfd[1];
}
Talking to a Shell Command via a
Pipe: popen()
#include <stdio.h>
FILE *popen(const char *command, const char *mode);
int pclose(FILE *stream);
Pipes and stdio Buffering
● Since the file stream pointer returned by a
call to popen() doesn't refer to a terminal, the
stdio library applies block buffering to the file
stream.
Pipes and stdio Buffering (cont.)
● When we call popen() with a mode of w, then
output is sent to the child process only when
the stdio buffer is filled or we close the pipe
with pclose().
○ using fflush() or setbuf(fp, NULL) to ensure the child
process receives data immediately.
Pipes and stdio Buffering (cont.)
● If the process calling popen() is reading from
the pipe, things may not be so
straightforward.
○ Modifying the source code to include calls to setbuf()
or fflush().
○ Using pseudoterminal (Chapter 64)
FIFOs
● FIFOs are a variation on the pipe concept. The
important difference is that FIFOs can be used
for communication between any processes.
● A FIFO has a name within the file system
and is opened in the same way as a regular
file.
$ mkfifo [ -m mode ] pathname
or
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
FIFOs (cont.)
● Opening a FIFO for reading blocks until
another process opens the IFO for writing,
and vice versa for writing.
○ Using O_NONBLOCK flag to prevent blocking.
● Using FIFOs and tee(1) to create a dual
pipeline
$ mkfifo myfifo
$ wc -l < myfifo &
$ ls -l | tee myfifo | sort -k5n
Nonblocking I/O (O_NONBLOCK flag)
● open()
○ It allows a single process to open both ends of a
FIFO.
○ It prevents deadlocks between processes opening
two FIFOs.
Nonblocking I/O (O_NONBLOCK flag)
● A deadlock
● O_NONBLOCK affects the semantics of
subsequent read() and write() calls.
○ Using fcntl(fd, F_SETFL, flags) to enable/disable
O_NONBLOCK bit.
Semantics of read() and write() on
Pipes and FIFOs
● read()
Semantics of read() and write() on
Pipes and FIFOs (cont.)
● write()

TLPI - Chapter 44 Pipe and Fifos

  • 1.
    TLPI - Chapter44 Pipe and Fifos Shu-Yu Fu (shuyufu at gmail.com)
  • 2.
    Pipes ● Pipes canbe used to pass data between related processes. $ ls | wc -l
  • 3.
    Important Characteristics ofPipes ● A pipe is a byte stream ● Reading from a pipe ● Pipes are unidirectional ● Writes of up to PIPE_BUF bytes are guaranteed to be atomic ○ using fpathconf(fd, _PC_PIPE_BUF) to return the actual upper limit ● Pipes have a limited capacity ○ using fcntl(fd, F_SETPIPE_SZ, size) to change the capacity of the pipe referred to by fd ○ using fcntl(fd, F_GETPIPE_SZ) to get the capacity of the pipe referred to by fd
  • 4.
    Creating and UsingPipes #include <unistd.h> int pipe(int filedes[2]);
  • 5.
    Creating and UsingPipes (cont.) ● We can also use the stdio functions (printf(), scanf(), and so on) with pipes by first using fdopen() to obtain a file stream corresponding to one of the descriptors in fieldes. ○ Using ioctl(fd, FIONREAD, &cnt) to get the number of unread bytes in the pipe referred to by fd
  • 6.
    A pipe hasfew uses within a single process
  • 7.
    A pipe hasfew uses within a single process (cont.) ● If we require bidirectional communication, there is a simpler way: just create two pipes, one for sending data in each direction between the two processes. ○ deadlocks may occur if both processes block while trying to read from empty pipes or while trying to write to pipes that are already full
  • 8.
    Closing unused pipefile descriptors ● Ensuring a process doesn't exhaust its limited set of file descriptors. ● It is only after all file descriptors in all processes that refer to a pipe are closed that the pipe is destroyed.
  • 9.
    Pipes as aMethod of Process Synchronization ● Listing 44-3: Using a pipe to synchronize multiple processes ● It can be used to coordinate the actions of one process with multiple other (related) processes. ● The fact that multiple (standard) signals can't be queued makes signals unsuitable in this case. But signals can be broadcasted by one process to all of the members of a process group.
  • 10.
    Using Pipes toConnect Filters ● Listing 44-4: Using a pipe to connect ls and wc ● dup2() allows us to explicitly specify the descriptor to be bound int pfd[2]; pipe(pfd); if (pfd[1] != STDOUT_FILENO) { dup2(pfd[1], STDOUT_FILENO); close(pfd[1]; }
  • 11.
    Talking to aShell Command via a Pipe: popen() #include <stdio.h> FILE *popen(const char *command, const char *mode); int pclose(FILE *stream);
  • 12.
    Pipes and stdioBuffering ● Since the file stream pointer returned by a call to popen() doesn't refer to a terminal, the stdio library applies block buffering to the file stream.
  • 13.
    Pipes and stdioBuffering (cont.) ● When we call popen() with a mode of w, then output is sent to the child process only when the stdio buffer is filled or we close the pipe with pclose(). ○ using fflush() or setbuf(fp, NULL) to ensure the child process receives data immediately.
  • 14.
    Pipes and stdioBuffering (cont.) ● If the process calling popen() is reading from the pipe, things may not be so straightforward. ○ Modifying the source code to include calls to setbuf() or fflush(). ○ Using pseudoterminal (Chapter 64)
  • 15.
    FIFOs ● FIFOs area variation on the pipe concept. The important difference is that FIFOs can be used for communication between any processes. ● A FIFO has a name within the file system and is opened in the same way as a regular file. $ mkfifo [ -m mode ] pathname or #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode);
  • 16.
    FIFOs (cont.) ● Openinga FIFO for reading blocks until another process opens the IFO for writing, and vice versa for writing. ○ Using O_NONBLOCK flag to prevent blocking. ● Using FIFOs and tee(1) to create a dual pipeline $ mkfifo myfifo $ wc -l < myfifo & $ ls -l | tee myfifo | sort -k5n
  • 17.
    Nonblocking I/O (O_NONBLOCKflag) ● open() ○ It allows a single process to open both ends of a FIFO. ○ It prevents deadlocks between processes opening two FIFOs.
  • 18.
    Nonblocking I/O (O_NONBLOCKflag) ● A deadlock ● O_NONBLOCK affects the semantics of subsequent read() and write() calls. ○ Using fcntl(fd, F_SETFL, flags) to enable/disable O_NONBLOCK bit.
  • 19.
    Semantics of read()and write() on Pipes and FIFOs ● read()
  • 20.
    Semantics of read()and write() on Pipes and FIFOs (cont.) ● write()