1
InterProcess Communication
Unix Pipes
Overview
q Communication between processes
- Pipe between two processes
- Redirecting stdin and stdout
2
Communication Between Processes
different machines
same machine
Interprocess Communication q Anonymous pipes
- Related processes on the same machine - Used mostly for a pipeline of filters
q Named pipes (or FIFO) - Unrelated processes (may be on different machines) - Used to exchange data over the pipe
q Sockets - Unrelated processes on any machines - Used for client/server communication (e.g., Web)
3
Preliminaries:
File Descriptors and System I/O
File Descriptors
Opera&ng System
stdio Library
FILE * fp = fopen("readme", "r");Process
User process
0 read1 write2 write34...
Process File Descriptor Table (FDT)
read
stdin data stdout data stderr data
File descriptor (integer)
readme data
int fd = open("readme", O_RDONLY);
fread(fp, ...);
read(fd, ...);supervisor mode
• When you open a file, the OS creates an entry to store info about the file
• The entry number is the file descriptor
user mode
4
Standard File Descriptors q File descriptor 0 is stdin q File descriptor 1 is stdout q File descriptor 2 is stderr
q Automatically opened for each program
Opera&ng System
scanf(...);User process
read(0, ...);
printf(...);
write(1, ...);
Main UNIX System Calls for Filesint open(char * pathname, int flags);
Open the file pathname and return a file descriptorint close(int fd);
Close a file descriptor fd int read(int fd, void * buf, int count);
Read up to count bytes from fd, into the buffer buf
int write(int fd, void * buf, int count);Writes up to count bytes to fd, from the buffer buf
5
Example: UNIX read() System Call• Read data from an open file
int read(int fd, void *buf, int count);
• Parameters! File descriptor fd: integer descriptor returned by open()! Buffer buf: pointer to memory to store the bytes it reads! count: maximum number of bytes to read
• Returns! Number of bytes read
– 0 if nothing more to read, -1 if an error
• Example usechar buf[MAX];int fd, n;fd = open(“readme”, O_RDONLY);n = read(fd, buf, MAX);
Example: A Simple getchar() #define MAX 1
int getchar() { char buf[MAX]; if (read(0, buf, MAX) == 1) return buf[0]; else return EOF; }
Read one character from stdin ! File descriptor 0 is stdin ! 1 is the number of bytes to read
Read returns the number of bytes read ! In this case, 1 byte means success
6
Test Program q Write a simple test program that uses read/write to read a
string from the standard input and write it back to the standard output.
Back to Anonymous Unix Pipes
7
q A pipe is an operating system buffer used to pass data from one process to another
q Pipes enable ONE WAY communication
Pipes
pipe (system buffer)
Example Use of Pipes q List information about processes owned by mdamian:
ps –ef | grep mdamian
Output of ps becomes input for grep
ps grep
8
Multiple Pipes? q How many processes belong to mdamian?
ps –ef | grep mdamian | wc –l
q The Unix shell creates 3 processes with two pipes between them
ps process grep process wc process
Other Examples q Display who is logged in, in alphabetical order:
who | sort
q Count the number of files in the current directory: ls | wc -l
who sort
ls wc
9
Creating a Pipe
q Pipe is an abstract communication channel - Process A can write to one end using the write system call - Process A can red from the other end using the read system call
q Creating a pipe int pipe(int fd[2]);ü return 0 upon success, -1 upon failure ü fd[0] is open for reading ü fd[1] is open for writing
q Two coordinated processes created with fork can pass data to each other using a pipe
int ret, p[2];...if(pipe(p) == -1) exit(1);ret = fork();
if(ret == 0) { /* child */ close(p[1]); ... read using p[0] as file descriptor ... close(p[0]); /* sends EOF to the reader */}else { /* parent */ close(p[0]); ... write using p[1] as file descriptor till EOF ... close(p[1]); wait(NULL);}
OS
Pipe Example Parent
p[0] p[1]
pipe p
Child
p[0] p[1]
10
int ret, p[2];...if(pipe(p) == -1) exit(1);ret = fork();...
q Parent creates a pipe, then forks a child q Child inherits the file descriptor table (and so the pipe) q Pipe is used between parent and child in one direction
OS
Pipe Example Parent
p[0] p[1]
pipe p
Child
p[0] p[1]
Exercise: Starting with this example, write a simple test program for pipes.
Dup2 q dup2 duplicates a file descriptor value
q As a result, fd2 will refer to the same device as fd - closes fd2 if it was in use
dup2(fd, fd2);
File descriptor data
FDT before dup2
File descriptor data
0 1 2 ... fd2
fd
0 1 2 ... fd2
fd
FDT a;er dup2
11
Dup2 q Commonly used to redirect stdin/stdout q Example: redirect stdout to “foo”
int fd;fd = open(”foo", O_RDWR); /* foo must exist */dup2(fd, 1);close(fd);...printf(...); /* to foo */
0 read1 write2 write34...
FDT stdin data stdout data stderr data foo data write
int ret, p[2];if(pipe(p) == -1) exit(1);ret = fork();
if(ret == 0) { /* child */ close(p[1]); dup2(p[0], 0); /* read end of pipe takes role of stdin */ close(p[0]); ... read from stdin or invoke new program with execv ...}else { /* parent */ close(p[0]); dup2(p[1], 1); /* read end of pipe takes role of stdin */ close(p[1]); ... write to stdout ... wait(NULL);}
Pipes and stdin/stdout
12
Activity q Write a program factorial that reads an integer from the
command line and calculates its factorial bash$ factorial 50 3041409320171337…
q Easy to code 1 * 2 * 3 * 4 * … *49 * 50 - But the product is much too large to fit into an integer or a long - Try the program bc (handles any size integers) bash$ bc
1*2*3*…*50 3041409320171337…
q Solution: use bc inside the factorial program
Structure of the factorial program q Create a pipe q Fork a child (who will inherit the pipe) q Parent
- write “1*2*3* … *50\n” into the pipe - write “quit\n” into the pipe (to terminate the child) - wait for the child to finish executing
q Child - redirect stdin to the read end of the pipe - invoke the program bc using execv
(bc will read from the pipe, compute the result, print it out) (Op=onal): Instead of the fixed value 50, have the parent read an integer N from the user, then write 1*2*3 … *N\n into the pipe - Use sprinI(buf, “%d”, x) to turn integer x into a string, then write it immediately into
the pipe
13
Conclusion q System calls for interprocess communication
- Pipe: create a pipe with a write end and a read end
- read/write: read from / write to a device identified by a file descriptor (an integer)
- dup2: duplicate a file descriptor