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.
Post a Comment