Lab 9 CIS 370 Umass Dartmouth. A pipe is typically used as a one-way communications channel which...

26
Lab 9 CIS 370 Umass Dartmouth

Transcript of Lab 9 CIS 370 Umass Dartmouth. A pipe is typically used as a one-way communications channel which...

Page 1: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Lab 9

CIS 370

Umass Dartmouth

Page 2: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

A pipe is typically used as a one-way communications channel which couples one related process to another.

UNIX deals with pipes the same way it deals with files.

A process can send data ‘down’ a pipe using a write system call and another process can receive the data by using read at the other end.

Page 3: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

$ who | sort

This command causes the shell to start the commands who and sort simultaneously.

The ‘|’ symbol in the command line tells the shell to create a pipe to couple the standard output of who to the standard input of sort.

The final result of this command should be a nicely ordered list of the users logged onto this machine.

Page 4: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

The who command on the left side of the pipe does not know that its stdout is being sent to a pipe.

The who command simply writes to stdout.

Similarly the sort command does not know that it is getting its input from a pipe.

The sort command simply reads the stdin.

Both commands behave normally!

Page 5: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

The overall effect is logically as if the following sequence has been executed.

$ who > sometempfile.txt

$ sort sometempfile.txt

$ rm sometempfile.txt

Flow control is maintained automatically by the OS (if who writes faster than sort can read, who is suspended, until sort catches up).

Page 6: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

#include <unistd.h>

Within programs a pipe is created using the system call pipe().

int pipe(int filedes[2]);

If successful, this call returns two file descriptors:

one for writing down the pipe,

one for reading from it.

Page 7: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

filedes is a two-integer array that will hold the file descriptors that will identify the pipe.

If successful, filedes[0] will be open for reading from the pipe and filedes[1] will be open for writing down it.

pipe() can fail (returns -1) if it cannot obtain the file descriptors (exceeds user-limit or kernel-limit).

Page 8: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.
Page 9: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

This sample code available online:

www.cis.umassd.edu/~jplante/cis370/lab09/samples/pipes.c

Page 10: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

The output of pipes.c:

Hello, World #1

Hello, World #2

Hello, World #3

Page 11: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Pipes behave first-in-first-out, this cannot be changed; lseek() will not work in pipes!

The size of the read and write don’t have to match (For example, you can write 512 bytes at a time while reading 1 byte at a time).

The previous example is trivial as there is only one process involved and the process is sending messages to itself!

Pipes become powerful when used with fork().

Page 12: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.
Page 13: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

This sample code available online:

www.cis.umassd.edu/~jplante/cis370/lab09/samples/pipes_2.c

Page 14: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Do you see a problem here?

What happens if both attempt to write and read at the same time?

Pipes are meant as uni-directional communication devices.

Page 15: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.
Page 16: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

This sample code available online:

www.cis.umassd.edu/~jplante/cis370/lab09/samples/pipes_3.c

Page 17: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

We now have a uni-directional pipe connecting two processes!

Page 18: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Closing the write file descriptor If all processes close the write-only end of the

pipe and the pipe is empty, any process attempting a read will return no data (will return 0 like EOF).

Closing the read file descriptor If all processes close the read-only end of the

pipe and there are processes waiting to write to the pipe, the kernel will send a SIGPIPE signal. If the signal is not caught the process will terminate. If the signal is caught, then after the interrupt routine

has completed, write will return -1.

Page 19: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.
Page 20: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

This sample code available online:

www.cis.umassd.edu/~jplante/cis370/lab09/samples/pipes_4.c

Page 21: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Included with these slides are those from previous semesters covering other topics related to pipes. This material was not covered because it is mostly unrelated to today’s lab assignment.

Identifying the size of a pipe to prevent writing too much data.

Non-blocking reads and writes on pipes. Using select() system call to handle multiple pipes. Pipes with exec(). FIFOs (named pipes).

You should review Chapter 7 of the lab textbook for comprehensive explanations of these topics.

Page 22: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

You will write a C program which opens FOUR pipes, P1, P2, P3 and P4. Your program should then create three children, C1, C2, and C3 (all in the same generation) as shown in the family tree below.

Parent

C1 C2 C3

Page 23: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

The structure of pipes and processes should look as follows:

Parent

C1

C2

C3

P1

P2

P3 P4

Page 24: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Your program should behave as follows: AFTER opening the pipes and creating the children, the

parent process should prompt the user for the number of messages to pass. Only the parent should know this value.

Once the parent knows how many messages to expect from the user, it should prompt the user for those messages in the form:

“<message string> <child to receive message>” You may assume that messages are only one word in

length (you do not need to handle spaces in messages). The parent will then use pipes P1 and P2 to send all the

messages to the appropriate children. Because C2 and C3 share pipe P2, they may receive each

other’s messages. In this situation, they are responsible for using P3 or P4 to forward the messages as appropriate.

Page 25: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Each process should ensure that its pipes are unidirectional.

Once received, messages MUST be printed out in the form

“Child <x> read message: <msg>”

Where <x> is the number of the child (1, 2, 3) that is printing the message and <msg> is the message itself.

Hint: To avoid blocking reads in the children, you should consider what happens when processes close one end of a pipe.

Hint: When sending messages to C2 and C3, you may want to append a special character to the message so that they will know if it was meant for them or not.

Hint: It’s probably a good idea to perform all the writes before performing any reads.

Page 26: Lab 9 CIS 370 Umass Dartmouth.  A pipe is typically used as a one-way communications channel which couples one related process to another.  UNIX deals.

Example execution:

$ ./myPipes 3

$ 3 messages to send from parent.

$ Message 1 (<msg> <child>): Hello 1

$ Message 2 (<msg> <child>): World 3

$ Message 3 (<msg> <child>): Goodbye 2

$ All messages sent!

$ Child 1 read: Hello

$ Child 2 read: Goodbye

$ Child 3 read: World

$ C1 exiting...

$ C3 exiting...

$ C2 exiting...

$ Parent exiting...

$