- A pipe is a communication between two processes, such that output of one process becomes the input of another process.
- There are two types of pipes: named pipes and unnamed pipes(anonymous pipes).
- Unlike other forms of inter-process communication(IPC), an un-named pipe is a one way communication.
- For two-way communication between processes, two pipes can be set up, one for each direction.
- Communication is achieved by one process writing into the pipe and other process reading from the pipe.
- One process cannot read from the buffer until another has written into to it.
- A limitation of un-named for inter-process communication is that that the processes using pipes must be related like having a common parent or between parent process and child process obtained via fork() API.
- Anonymous pipes are always local; they cannot be used for communication over a network.
- The UNIX command-line interpreter(e.g., csh) provides the pipe facility.
- ps -aux | grep 1234
- This command gives the process utility output to another utility name grep.

The shell arranges the standard input and output of the two commands, so that
- The standard input to cmd1 comes from the terminal keyboard.
- The standard output form cmd1 is fed to cmd2 as its standard input.
- The standard output from cmd2 is connected to the terminal screen
Pipe System call
- The pipe() system call would create a pipe for one way communication.
- This pipe exists in an main memory and is treated as virtual file.
- If a process tries to read before something is written, the process is suspended until something is written.
- The pipe system call finds the first two available positions in the processes open file table and allocates them for read and write ends of the pipe.
int pipe (fd[2]);
- It creates two file descriptors, that is fd[0]] for reading and fd[1] for witting.
- It returns 0 on success and -1 on failure.
Sample Program-1:
This is a simple program for showing the use of pipe within a single process.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int pipe_fd[2];
int data_processed;
char buffer[20];
char *msg = "Hello how are you";
memset (buffer, '\0', sizeof(buffer));
int result = pipe (pipe_fd);
if (result == -1)
{
printf("\n Pipe creation failed %s\n", strerror(errno));
exit (EXIT_FAILURE);
}
printf("\n Pipe created successfully..\n");
printf("\n Pipe read descriptor: %d\n", pipe_fd[0]);
printf("\n Pipe write descriptor: %d\n", pipe_fd[1]);
data_processed = write (pipe_fd[1], msg, strlen(msg));
printf("\n Data send is: %s, length is: %d\n", msg, data_processed);
data_processed = read (pipe_fd[0], buffer, sizeof(buffer));
printf("\n Data read is: %s, length is: %d\n", buffer, data_processed);
return 0;
}
Output:
gcc pipe.c
./a.out
Pipe created successfully..
Pipe read descriptor: 3
Pipe write descriptor: 4
Data send is: Hello how are you, length is: 17
Data read is: Hello how are you, length is: 17
...Program finished with exit code 0
Press ENTER to exit console.
The above program could have even done with file, the real advantage of pipe comes when data is passed between process.
Sample Program-2:
This program is for sending data between process, parent and child process created using fork() and wait(). Please refer fork() and wait() for a clear understanding of the below program.
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
int pipe_fd[2];
int data_processed;
char buffer[20];
char *msg = "Hello how are you";
memset(buffer, '\0', sizeof(buffer));
int result = pipe (pipe_fd);
if (result == -1)
{
printf("\n Pipe creation failed %s\n", strerror(errno));
exit (EXIT_FAILURE);
}
printf("\n Pipe created successfully\n");
result = fork();
if (result == -1)
{
printf("\n Fork failed %s\n", strerror(errno));
exit (EXIT_FAILURE);
}
if (result !=0) /* Parent process */
{
int stat_val;
data_processed = write (pipe_fd[1], msg, strlen(msg));
printf("\n Data send is: %s of length: %d\n", msg, data_processed);
/* wait() is called so that the child terminates before the parent and resources of child are freed, else it may create zombie process */
printf("\n Waiting for child to finish\n");
int child_pid = wait (&stat_val);
if (child_pid == -1)
{
printf("\n There is no child process \n");
exit(EXIT_FAILURE);
}
if (WIFEXITED(stat_val))
printf("\n Child terminated Normally\n");
else
printf("\n Child terminated Abnormally");
}
if (result ==0) /* Child process */
{
data_processed = read (pipe_fd[0], buffer, sizeof(buffer));
printf("\n Data read is: %s of length: %d\n", buffer, data_processed);
}
return 0;
}
Output:
gcc pipe.c
./a.out
Pipe created successfully
Data send is: Hello how are you of length: 17
Waiting for child to finish
Data read is: Hello how are you of length: 17
Child terminated Normally
Sample Program-3:
This is for use of pipe() for data transfer among parent and child process but child process is a different program from its parent. The child process execute a new program by the use execl() function call. Please read fork(), wait(), execl() functions call for the better understanding of the below program
Parent process(pipe_execl.c)
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int main()
{
int pipe_fd[2];
int data_processed;
char *msg = "Hello how are u";
char buffer[10];
memset (buffer, '\0', sizeof(buffer));
int result = pipe (pipe_fd);
if (result == -1)
{
printf ("\n Pipe creation failed %s\n", strerror(errno));
exit (EXIT_FAILURE);
}
printf ("\n Pipe created successfully\n");
result = fork();
if (result == -1)
{
printf ("\n Fork failed %s\n", strerror(errno));
exit (EXIT_FAILURE);
}
if (result !=0) /* Parent process */
{
int stat_val;
data_processed = write (pipe_fd[1], msg, strlen(msg));
printf ("\n Data send is: %s of length: %d\n", msg, data_processed);
printf ("\n Waiting for child to finish\n");
int child_pid = wait (&stat_val);
if (child_pid == -1)
{
printf ("\n There is no child process \n");
exit (EXIT_FAILURE);
}
if (WIFEXITED(stat_val))
printf("\n Child terminated Normally\n");
else
printf("\n Child terminated Abnormally");
}
else /* Child process */
{
sprintf (buffer, "%d", pipe_fd[0]);
result = execl ("pipe_new_image", "pipe_execl", buffer, NULL);
if (result == -1)
{
printf ("\n execl failed %s\n", strerror(errno));
exit (EXIT_FAILURE);
}
}
return 0;
}
Child process(pipe_new_image.c)
#include <stdio.h>
#include <string.h>
int main (int argc, char *argv[])
{
printf ("\n Executing new image\n");
int data_processed, fd;
char buffer[20];
memset (buffer, '\0', sizeof(buffer));
sscanf (argv[1], "%d", &fd);
data_processed = read (fd, buffer, sizeof(buffer));
printf ("\n Data read is: %s of length: %d\n", buffer, data_processed);
return 0;
}
Output:
[aprakash@wtl-lview-6 thread]$ gcc pipe_new_image.c -o pipe_new_image
[aprakash@wtl-lview-6 thread]$ gcc pipe_execl.c
[aprakash@wtl-lview-6 thread]$ ./a.out
Pipe created successfully
Data send is: Hello how are u of length: 15
Waiting for child to finish
Executing new image
Data read is: Hello how are u of length: 15
Child terminated Normally
Related Topics:
- Named Pipe.
- Difference between named and unnamed pipe.
- Difference between named pipe and regular file.
- Broken pipe error.
- Named pipe vs TCP IP socket.
Categories: Operating system (OS)
Excellent composition at a glance
LikeLike