
Lecture 09 Pipes
Outline • Pipes in General • pipe() system call • pipe() and fork() • Closing Unused File Descriptors • pipe() and dup2() • Live Coding
Pipes • Pipes are the oldest type of interprocess communication (IPC) in UNIX • The output of one process becomes the input of another
Pipes (Example) UNIX> ls | wc –l • | => shell command to pipe processes together • pipe the output of process ls to the process wc –l
Pipes (Example) UNIX> ls | wc –l • stdout from lsprocess joined with write end of pipe • stdinof wcprocess joined with read end of pipe • Two processes are unaware of pipe • (Just writes to stdout/ reads from stdin) • Pipe creates IPC pipe wc -l stdin (f 0) ls stdout (fd 1) write end read end
Pipes UNIX> ls | wc –l Shell • Creates a pipe • Creates two child processes using fork() and exec() • Child #1 duplicatesstdout with write end of pipe • Child #2 duplicatesstdinwith read end of pipe • Parentand childrenclose all unused FDs
Pipes • Pipe data is just a stream of bytes • Cannot use lseek() with a pipe • To send discrete messages, use alternate IPC methods • Sockets • Message queues • etc.
Reading from a Pipe • Read will block until a byte is present in pipe • When write end of pipe is closed, read will see EOF
Pipes are Unidirectional • Data can travel only in one direction • One end used for writing • The other end used for reading • Want bidirectional IPC? Use sockets..
Outline • Pipes in General • pipe() system call • pipe() and fork() • Closing Unused File Descriptors • pipe() and dup2() • Live Coding
pipe() int pipe ( intfd[2] ); • #include <unistd.h> • Returns 0 on success • Returns -1 on error • pipe() returns two file descriptors in fd array • fd[0] => read end of pipe • fd[1] => write end of pipe
pipe() int pipe ( intfd[2] ); • After pipe(), can use normal I/O system calls on fd[0] and fd[1] • Can also use C I/O functions: fprintf, fscanf, etc. • Use fdopen() to obtain a FILE * from file descriptor
pipe() • After pipe(), calling process has FDs to both ends: calling process fd[1] fd[0] pipe
Outline • Pipes in General • pipe() system call • pipe() and fork() • Closing Unused File Descriptors • pipe() and dup2() • Live Coding
pipe() and fork() parent process fd[1] fd[0] • Pipes often used for IPC between parent and child • Remember: after fork(), child inherits copies of parent’sFDs pipe child process fd[1] fd[0] after fork()
pipe() and fork() parent process fd[1] • One process should close unusedread end of pipe • Other process should close unusedwriteend of pipe • E.g., if parent wants to send data tochild, parent would close fd[0] (read end), child would close fd[1] (write end) pipe child process fd[0] after closing unused FDs
Outline • Pipes in General • pipe() system call • pipe() and fork() • Closing Unused File Descriptors • pipe() and dup2() • Live Coding
Closing Unused FDs • Essential to correct use of pipes • Process on reading end of pipe must closewrite end • Else the truewrite end of pipe will never send EOF • Why? Because the a write end of the pipe is still open • ==> Read from pipe will block forever
Closing Unused FDs • Essential to correct use of pipes • Process on writing end of pipe must close read end • Else data can still be written to pipe even after read end is closed • Moral of the story? Always close unused pipe FDs
Outline • Pipes in General • pipe() system call • pipe() and fork() • Closing Unused File Descriptors • pipe() and dup2() • Live Coding
Using Pipes to Connect Filters • Many pipes can be linked together, e.g., UNIX> ls –l | head –n 3 | wc –c | ... • stdout from the left process is piped to stdinof right process... • Shell does this by duplicatingstdoutof left process to write end of pipe ( fd[1] ) ... and duplicatingstdinof right process to read endof pipe ( fd[0] )
Using dup2() with pipe() dup2( fd[1], 1 ) • Close file descriptor 1 ( stdout ) • Reopen file descriptor 1 bound to write end of pipe ( fd[1] ) • After dup2(), now have two FDs referring to write end of pipe • File descriptor 1 ( stdout) • fd[1] • Must then close fd[1] ( duplicated descriptor )
Outline • Pipes in General • pipe() system call • pipe() and fork() • Closing Unused File Descriptors • pipe() and dup2() • Live Coding
Live Coding • Create pipe, fork child process, IPC between parent / child • Create pipe, fork / exec new program, IPC between parent / new program • Recreate “ls | wc –l” (create pipe, fork two processes, dup, exec)