CE 466 System Programming
Interprocess Communication (IPC) Pipes
Computer Engineering Department Yarmouk University 10/27/2008
Pipes • Pipes are the simplest Unix inter-process communication mechanisms. • The pipe() system call creates a buffer that the caller process can access through file descriptors. • The data is written to one file descriptor and is read from the other on a first-in-first-out basis.
1
Pipes #include int pipe(int P[2]);
• system call used to create a pipe ¾Where p is a two element integer array ¾P[1]: file descriptor on upstream end of pipe ¾P[0]: file descriptor on downstream end of pipe P[1]
P[0]
• If successful, pipe returns 0. If unsuccessful, pipe returns –1 and sets errno.
Pipes user process read fd write fd
Æflow of data Æ pipe
2
IPC Using Pipes •
Pipes are typically used to communicate between two different processes: • • •
Process A (parent) creates a pipe Process A forks twice, creating B and C. Each process closes the ends of the pipe it does not need. • • •
•
Process B closes downstream end Process C closes upstream end Process A closes both ends
Processes B and C execute other programs, using exec, where file descriptors are retained.
Using Pipes Parent process A
Reading process
pipe() fork()
Close the writing end of pipe
Close both ends of pipe read() A loop
close(…) exit()
Writing process
fork() Close the reading end of pipe write() pipe wait()
A loop close(…) exit()
wait() Continue or exit
3
Child B
Child C Process read read fd fd
write write fd fd
Kernel
Pipe Pipe
Synchronization Using Pipes • Have finite capacity (few hundred bytes) • This imposes loose synchronization between up and down stream processes: ¾Upstream process blocks if pipe is full Until downstream consumes some
¾Downstream process blocks if pipe is empty Until upstream writes some
• If upstream closes descriptor, a downstream read operation will return EOF (0)
4
• Closing upstream end of pipe is essential for 1st (reading) process or it will never see EOF. • A pair of wait() are there to ensure that parent will not return before both children have finished.
How to Create a Pipe #include #include #include #include
<stdio.h> <string.h> <sys/types.h>
int fd[2]; if (pipe(fd) == -1) perror("Failed to create the pipe");
5
Synchronization Using Pipes While ((count=read(fd, buffer, 100)) > 0 ) { //process data }
Two Way Communication Using Pipes Parent Process
Child Process
write write fd fd read read fd fd
read read fd fd write write fd fd
Kernel Flow of Data Pipe Pipe Pipe Pipe Flow of Data
6
Redirection #include int dup2(int FileDesc1, int FileDesc2);
• • • •
Closes entry FileDesc1 of the file descriptor table if open Copies the pointer of entry FileDesc1 into entry FileDesc2 Returns the file descriptor value that was duplicated Example: fd = open("my.file“,O_RDRW ) dup2(fd,1)
Example % ls | sort • The shell gets the output of “ls” connected to the upstream end of the pipe, and the input to “sort” connected to the downstream end. • Shell uses dup2 to do the plumbing: ¾ dup2(old, new): ¾ takes an existing file descriptor (old) and duplicates it into (new location). int p[2]; pipe(p); dup2(p[1], 1); /*standard output connected upstream end of pipe*/
7
Example main() { int fds[2]; pipe(fds); /*child 1 duplicates downstream into stdin */ if (fork() == 0) { dup2(fds[0], 0); close(fds[1]); execlp(“sort”, “sort”, 0); } /*child 2 duplicates upstream into stdout */ else if fork() == 0) { dup2(fds[1], 1); close(fds[0]); execlp(“ls”, ”ls”, 0); } else{ /*parent closes both ends and wait for children*/ close(fds[0]); close(fds[1]); wait(0); wait(0); } }
Example
8
Characteristics of Pipes • Unidirectional • Pipes can only be used between processes that have a common ancestor (named pipes) • No mechanism to authenticate • Do not work across the network • They are the easiest of IPC mechanisms. Simple, easy to understand and easy to implement as well.
Midterm Exam
When: Where: How:
???? in class Closed book and notes
Cheat sheet ????
9