A pipe is an IPC mechanism that allows different processes to communicate with each other. This is the simplest of all the IPC methods available in Unix. A pipe is a one-way communication channel and is called an anonymous pipe. It passes a parameter, such as the output of one process to another process. The other process accepts this parameter as input. This input is temporarily retained by the system till the receiving process reads the input.
At the command prompt, a pipe is represented by a vertical bar (|) between two commands. The output of the first command is the input for the second command. A pipe has a fixed size of 4,056 bytes. For example, a pipe on a Unix shell may be written as:
$ls –la |more
The sequence in which the data is written to the pipe is the same as that in which the data is read from the pipe. Also, the delivery of the data is reliable. If the data is delivered in an unreliable manner, one of the processes - either the sender or the receiver - quits. In a program, a pipe is created by calling the pipe() system function. This function requires an array with two elements as an argument. The function returns two file descriptors in the two elements of the array.
Illustration of the pipe() System Function
#include <unistd.h> /* This defines the system function pipe() */
int main()
{
int arr[2]; /* An array of two elements */
pipe ( arr ); /Calls the pipe() function with array arr as its argument */
printf("arr[0] is %d\n arr[1] is %d\n", arr[0],arr[1]);
/* Prints the file descriptor values stored in the array elements */
return 0;
}
Creating read-write Pipe Using the pipe() System Function
#include<unistd.h> /* This defines the system function pipe() */
/*This header file defines perror() system function*/
#include <errno.h>
int main()
{
/*Defining an array to store two file descriptors */
int aray[2];
/*Create the pipe */
int fldesc = pipe (aray);
if (fldesc == -1)
{
perror("call to pipe() system function failed");
exit(1);
}
return 0;
}
Following code is an example of a two-process system. Here, one process, the parent process, reads the input from the user and sends this input to the other process, the child process. The child process then prints the data to the screen. Here, the data is sent through the pipe. The rule applied here is that every byte passed through the pipe represents a single character typed by a user.
#include<stdio.h>/* Defines standard I/O routines. */
#include<unistd.h>/*Defines the pipe () system function*/
void chldhandler(int txt[])
{
int pdc;/* Data received from the parent. */
int rtst;/* Returns the return status of read().*/
close(txt[1]);
while ((rtst = read(txt[0], &pdc, 1)) > 0)
{
putchar(pdc);
}
exit(0);
}
void prnthandler(int txt[])
{
int udc;/* Data received from the user. */
int rtstgc;/* Returns the return status of getchar(). */
/* Closing the not required read-part of the pipe. */
close(txt[0]);
/* Entering a loop to read user input and writing it to the pipe. */
while ((udc = getchar()) > 0)
{
/* write the character to the pipe. */
rtstgc = write(txt[1], &udc, 1);
if (rtstgc == -1)
{
perror("write failed in the parent process!");
close(txt[1]);
exit(1);
}
}
close(txt[1]); /* Closes the pipe, to inform the child process about its completion */
exit(0);
}
/*The main function. */
int main(int argc, char* argv[])
{
int txt[2]; /* An array to store the file descriptors of the pipe. */
int procid; /* pid of child process, or 0, as returned via fork. */
int rtstf; /* stores return values of various routines. */
rtstf = pipe (txt);
if (rtstf == -1)/*When pipe creation fails*/
{
perror("pipe creation fails!");
exit(1);
}
/* Forking to create a child process, and set the handling routines. */
procid = fork();
switch (procid)
{
case -1 :
perror("fork() system functionfails!");
exit(1);
case 0:
chldhandler(txt);
/* Not executed*/
default:
prnthandler(txt);
/* Not executed */
}
return 0;/* Not executed */
}
In Unix, pipes are created by calling system functions. There are two methods available in Unix to open a file. They are:
- popen(): Is called formatted piping.
The syntax of popen() is:
FILE *popen(char *command, char *type)
This declaration opens a pipe for I/O. The popen() function receives two parameters. Both these parameters are pointers of the char type. The first parameter represented is a process that connects to the calling process. This creates a pipe. The second parameter is the type that may be either in reading (r) or writing (w) mode. The popen() function returns a stream pointer or NULL value if any error occurs. When a pipe is opened with a call to the popen() function, it is mandatory to close this pipe by calling the pclose(FILE *stream) function. To communicate with the pipe’s stream, the fprintf() and fscanf() functions are used. - pipe(): Is called low-level piping.
The syntax of the function pipe() is:
int pipe(int fldr[2])
This declaration opens a pipe. The function requires an argument of the type, integer array, fldr[2]. The array has two elements. The first element of the array, fldr[0], is used for reading, and the array element, fldr[1], is used for writing. The pipe() function returns 0 when it succeeds and –1 when it fails. It also displays an error message on failure. After the pipes are created, two or more processes are created by a fork and are passed using the read() and write() functions.
Illustration of a Parent Process Writing to a Child Process
#include<unistd.h>
int prntdesc [2];
pipe(prntdesc);
int main()
{
if (fork() == 0 )
{ /* Creates child process */
close (prntdesc [1]);
/* This reads from the parent process.*/
read (prntdesc [0]);
}
else
{
close (prntdesc [0]);
write (prntdesc [1]);
}
return 0;
}


Currently Active Users
Categories
Latest Blog Entries

Rate this article