Outline ● What is a pipe? CSCI 4730/6730 ● UNIX System review Systems Programming Refresher ● Processes (review) ● Pipes ● FIFOs Pipes & FIFOs 1 2 Maria Hybinette, UGA Maria Hybinette, UGA What is a Pipe? Example: Shell Pipes ● Example: ● A pipe is a one-way (half-duplex) » who communication channel which can be used – outputs � who � is logged onto the system (e.g. on atlas) to link processes. » wc -l hello.txt – outputs counts the number of lines in the file hello.txt ● Can only be used between processes that ● You have seen pipes at the UNIX shell level already: have a common ancestor » who | wc -l ● Shell starts the commands who and wc -l to run ● A pipe is a generalization of the file concept concurrently. » can use I/O functions like read() and write() to ● | tells the shell to create a pipe to couple standard receive and send data output of � who � to the standard input of � wc -l � , Recall < and > logically: redirects standard input » {atlas:maria:195} who > tmpfile and output to a » {atlas:maria:196} wc -l < tmpfile file (i.e., file » 17 descriptor 0 for » {atlas:maria:197} input, and 1 for SVR4 UNIX - uses full duplex pipes (read/write on both file descriptors) 3 output. 4 Maria Hybinette, UGA Maria Hybinette, UGA {atlas:maria:195} who > tmpfile Programming with Pipes {atlas:maria:196} wc -l < tmpfile 17 {atlas:maria:197} who | wc -l Hello Gunnar! 17 Process Process Chat Chat {atlas:maria:197} cat tmpfile Maria Gunnar #include <unistd.h> � A � � B � luffman pts/44 Apr 26 10:17 (h198-137-28-67.paws.uga.edu) Hi Nice to Hear int pipe( int fd[2] ); imacs pts/25 Apr 26 08:43 (128.192.4.35) from you! cai pts/38 Apr 26 09:15 (user-1121m0h.dsl.mindspring.com) ● pipe() binds fd[] with two file descriptors: maher pts/20 Apr 26 04:57 (adsl-219-4-207.asm.bellsouth.net) luffman pts/50 Apr 26 09:52 (h198-137-28-67.paws.uga.edu) » fd[0] used to read from pipe (consumer) moore pts/55 Apr 26 10:43 (adsl-219-226-14.asm.bellsouth.net) tanner pts/117 Apr 26 08:46 (cmtspool-48.monroeaccess.net) » fd[1] used to write to pipe (producer) weaver pts/106 Apr 26 08:12 (creswell-s218h112.resnet.uga.edu) dimitrov pts/39 Apr 26 09:01 (128.192.42.142) ● Returns 0 if OK and -1 on error. User process steward pts/23 Apr 26 09:16 (128.192.101.7) weaver pts/12 Apr 26 08:14 (creswell-s218h112.resnet.uga.edu) ● Example error: fd[0] fd[1] dme pts/6 Apr 25 09:34 (128.192.4.136) ldeligia pts/40 Apr 26 10:10 (128.192.4.72) » too many fd open already. brownlow pts/13 Apr 26 09:48 (68-117-218-71.dhcp.athn.ga.charter.com) misztal pts/30 Mar 27 10:32 (kat.cs.uga.edu) pipe james pts/51 Apr 26 09:28 (adsl-35-8-252.asm.bellsouth.net) cs4720 pts/107 Mar 27 15:06 (druid) Kernel 6 Maria Hybinette, UGA
Example: Pipe within a single process Example: pipe-yourself.c write( p[1], msg1, MSGSIZE ); #include <stdio.h> write( p[1], msg2, MSGSIZE ); ● Simple example: #include <unistd.h> write( p[1], msg3, MSGSIZE ); #define MSGSIZE 16 /* null */ » creates a pipe called � p � for( i=0; i < 3; i++ ) { /* read pipe */ » writes three messages to the pipe (down the pipe) char *msg1= � hello, world #1 � ; read( p[0], inbuf, MSGSIZE ); char *msg2= � hello, world #2 � ; printf( � %s\n � , inbuf ); » reads (receives) messages from the pipe char *msg3= � hello, world #3 � ; } return 0; {saffron:ingrid:4} pipe-yourself int main() hello, world #1 } { ● Process (user) view: hello, world #2 char inbuf[MSGSIZE]; hello, world #3 pipe p int p[2], i; p[0] (read) if( pipe( p ) < 0 ) pipe p process { /* open pipe */ p[1] (write) perror( � pipe � ); p[0] (read) exit( 1 ); process } p[1] (write) 7 8 Maria Hybinette, UGA Maria Hybinette, UGA Example: Pipe between a parent Things to Note and child ● Pipes uses FIFO ordering: first-in first-out . 1. Creates a pipe » messages are read in the order in which they were written. 2. Creates a new process via fork() » lseek() does not work on pipes. 3. Parent writes to the pipe (fd 1) ● Read / write amounts do not need to be the 4. Child reads from pipe (fd 0) same, but then text will be split differently. ● Pipes are most useful with fork() which creates an IPC connection between the parent and the child (or between the parents children) parent parent child Pipe child child Pipe 9 10 Maria Hybinette, UGA Maria Hybinette, UGA Example: pipe-fork.c Things to Note if( pid > 0 ) /* parent */ { #include <stdio.h> write( p[1], msg1, MSGSIZE ); #include <sys/wait.h> ● Pipes are intended to be unidirectional #include <unistd.h> write( p[1], msg2, MSGSIZE ); channels if parent-child processes both read #define MSGSIZE 16 write( p[1], msg3, MSGSIZE ); wait( (int *) 0 ); and write on the pipe at the same time char *msg1= � hello, world #1 � ; } if( pid == 0 ) /* child */ char *msg2= � hello, world #2 � ; { confusion. char *msg3= � hello, world #3 � ; for( i=0; i < 3; i++ ) { ● Best style is for a process to close the links it int main() read( p[0], inbuf, MSGSIZE ); { printf( � %s\n � , inbuf ); does not need. Also avoids problems } char inbuf[MSGSIZE]; int p[2], i, pid; return 0; } (forthcoming). } if( pipe( p ) < 0 ) p[0] (read) p[0] (read) { /* open pipe */ perror( � pipe � ); exit( 1 ); } parent child parent child if( (pid = fork()) < 0 ) { perror( � fork � ); p[1] (write) p[1] (write) exit( 2 ); } 11 12 Maria Hybinette, UGA Maria Hybinette, UGA
Example: pipe-fork-close.c Some Rules of Pipes if( pid > 0 ) /* parent */ ● Every pipe has a size limit { #include <stdio.h> close( p[0] ); /* read link */ #include <sys/wait.h> » POSIX minimum is 512 bytes -- most systems makes this figure #include <unistd.h> write( p[1], msg1, MSGSIZE ); larger #define MSGSIZE 16 write( p[1], msg2, MSGSIZE ); write( p[1], msg3, MSGSIZE ); char *msg1= � hello, world #1 � ; wait( (int *) 0 ); if( pid == 0 ) /* child */ ● read() blocks if pipe is empty and there is a a write link open to char *msg2= � hello, world #2 � ; } { that pipe [it hangs] char *msg3= � hello, world #3 � ; close( p[1] ); /* write link */ for( i=0; i < 3; i++ ) ● read() from a pipe whose write() end is closed and is empty int main() { { returns 0 (indicates EOF ) [but it doesn’t hang] read( p[0], inbuf, MSGSIZE ); char inbuf[MSGSIZE]; printf( � %s\n � , inbuf ); int p[2], i, pid; » Lesson Learned: Close write links o/w read() will never return *** } } if( pipe( p ) < 0 ) return 0; } { /* open pipe */ ● write() to a pipe with no read() ends returns -1 and generates perror( � pipe � ); SIGPIPE and errno is set to EPIPE exit( 1 ); p[0] (read) } ● write() blocks if the pipe is full or there is not enough room to if( ( pid = fork() ) < 0 ) { support the write(). parent child perror( � fork � ); exit( 2 ); » May block in the middle of a write() } p[1] (write) 13 14 Maria Hybinette, UGA Maria Hybinette, UGA Example: Several Writers ● Perfectly possible to have multiple ● Since a write() can suspend in the middle of readers / writers attached to a pipe its output then output from multiple writers output may be mixed up (or interleaved ). » can cause confusion writer � maria was great… � � big tree… � writer � maria is getting big… � reader writer � …is getting a pizza… � 15 16 Maria Hybinette, UGA Maria Hybinette, UGA pipe-nonblocking.c Avoid Interleaving Non-blocking read() & write() ● Problem: Sometimes you want to avoid ● In limits.h , the constant PIPE_BUF gives read() and write() from blocking. the maximum number of bytes that can be output by a write() call without any chance ● Goals: of interleaving. » want to return an error instead ● Use PIPE_BUF is there are to be multiple » want to poll several pipes in turn until one has data writers in your code. ● Approaches: » Use fstat() on the pipe to get #characters in pipe (caveat: multiple readers may give a “race condition”) » Use fcntl() on the pipe and set it to O_NONBLOCK 17 18 Maria Hybinette, UGA pipe-nonblocking.c Maria Hybinette, UGA pipe-nonblocking.c
Recommend
More recommend