Operating System

Inter-Process Communication (PIPES)



 

Operating System

 

Inter-Process Communication (PIPES)

 

1.   Inter-process Communication

As the name suggests, sending messages or useful data between two processes. Shortly say IPC.

 

There are different mechanisms available for IPC. This lab will focus on the Process pipes mechanism.

 

2. Process Pipes

Piping is a process where the output of one process is made the input of another. LINUX users have seen examples of this from the UNIX command line using pipe sign ‘|’.

 

For your experience just do the following quick activity.

Lab Activity1

Step1: Following command will simply show you the contents of the directories and subdirectory’s contents of the current working directory. Try it out.

 

$find .

 

Step2: Above command will show you the whole output in one go. If you want to examine its output like file contents. Send the output of Step2 to another command “more”. You are already familiar with it in lab2.

 

Step3: Try the following command.

 

$find. | more

 

 Pipe sign in above the command is serving as “IPC pipe” taking the output of find and sending it to more as input.

3. Pipes in C

We will now see how we do this from C programs. We will have two forked processes and will communicate between them.

 

We must first open a pipe. UNIX allows two ways of opening a pipe.

 

·         Formatted Piping - popen()

 

·         Low level Piping – pipe() We will use the second one in this lab.

Note: Learn more about both in chapter 12, Beginning LINUX Programming by WROX – 2nd Edition

 

4. pipe()

It’s a low-level function to create a pipe. This provides a means of passing data between two programs, without any overhead. It also gives us more control over the reading and writing of data.

 

The pipe function has the prototype

 

#include <unistd.h>  // Header file required for using pipe()

 

int pipe(int file_descriptor[2]);

 

·         pipe() is passed (a pointer to) an array of two integer file descriptors. It fills the array with two new file descriptors

·         pipe() returns a zero on success. On failure, it returns −1 and sets an error to indicate the reason for failure. See man pages for error descriptions.

·         The two file descriptors returned are connected in a special way. Any data written to file_descriptor[1] can be read back from file_descriptor[0]. The data is processed on a first-in, first-out basis, usually abbreviated to FIFO. This means that if you write the bytes 1, 2, 3 to file_descriptor[1], reading from file_descriptor[0] will produce 1, 2, 3. This is different from a stack, which operates on a last-in, first-out basis, usually abbreviated to LIFO.

Important Note: It's important to realize that these are file descriptors, not file streams, so we must use the lower−level read and write calls to access the data, rather than fread and fwrite.

 

Let’s do the following lab activity to understand it practically!

 

Lab Activity2

 

Step1: Create a file with the name “pipe1.c”. Type in the following code.

 

#include <unistd.h>

 #include <stdlib.h>

 #include <stdio.h>

 #include <string.h>

int main()

{

int data_processed;

 int file_pipes[2];

const char some_data[] = "123";

char buffer[BUFSIZ + 1];

memset(buffer, '\0', sizeof(buffer));

 if (pipe(file_pipes) == 0) {

data_processed = write(file_pipes[1], some_data, strlen(some_data));

printf("Wrote %d bytes\n", data_processed);

data_processed = read(file_pipes[0], buffer, BUFSIZ); printf("Read %d bytes: %s\n", data_processed, buffer);

 exit(EXIT_SUCCESS);

 

}

 

 

 

Do

 

} exit(EXIT_FAILURE);

 

 

1.  Compile and run it.

 

2.  Reverse the order of the write and read and run the program again.

 

3.  Briefly describe what happened with the reversed order and why the program behaved that way.

 

4.  Modify pipe1.c in the following ways:

 

a.   Dynamically allocate buffer so it's exactly the right size for some_data.

 

b.   Copy the string from some_data into the buffer.

 

c.       Modify the read so its third argument is the exact size of the buffer (rather than the large BUFSIZ).

 

5.  Hand in your modified pipe1.c.

 

 

 

 

 

 

 

 

 

 

 

 

To Do

 

Lab Activity3: Pipes across a fork/exec

 

 

1.  Copy pipe3.c from shared folder/portal.

 

2.  Copy pipe4.c from shared folder/portal.

 

3.  Compile and run the program just to see what it does.

 

4.  Modify pipe3.c as follows:

 

a   Have the parent wait for the child.

 

b. Close the file descriptor of the read end of the pipe on the parent's side.

 

c.    Pass the write end of the pipe to the child as another command-line argument.

 

d.  Close the file the descriptor of the write end of the pipe on the child's side.

 

5  Hand in your modified pipe3.c and pipe4.c.

 

6. OK, there's one pipe. Parent (pipe3) "closes the read end." Child (pipe4) "closes the write end." So now both ends are closed, but the program still succeeds in writing to and reading from the pipe. Give a brief explanation of how this can be. Hint: read the man page for close and consider what a child inherits from its parent.

 

 

 

Lab Activity4: Multiple pipes across a fork/exec

In this task, you will write a program that has two-way communication between parent and child. Use Task 3 as a starting point, and add a second pipe to it.

 

To Do

 

1.    Copy pipe3.c to twoPipesParent.c

 

2.    Copy pipe4.c to twoPipesChild.c

 

3.     Modify twoPipesParent.c as follows:

 

 

 

 

a.   Add a second pipe that will be used for a message from the child to the parent.

 

b.    Close the appropriate file descriptors on both pipes.

 

c.     Pass both pipes' file descriptors to the child in the exec

 

d.  Send the message "Hi there, Kiddo" to the child over one pipe (as in Task 2). Print the PID and byte count as in Task 2.

E   Then, read a message from a child over the second pipe. Print the PID, byte count, and message text as in Task 2.

 

4.   Modify twoPipesChild.c as follows:

 

a.     Grab the file descriptors of both pipes from the argument list.

 

b.     Close the appropriate file descriptors.

 

c.     Read a message from the parent over the first pipe (as in Task 2). Print the PID, byte count, and message text as in Task 2.

d.    Then, send the message "Hi, Mom" to parents over the second pipe. Print the PID and byte count as in Task 2.

 

5.  Hand in twoPipesParent.c and twoPipesChild.c.

 

6.     Run the program multiple times.

 

7.      Write a brief description of the output you got from the program. Note carefully the order in which the output occurs. Briefly explain the output.

  

Lab Tasks Submission:
                                                 Click for Submission 

Post a Comment

Previous Post Next Post