A pipe is a medium for communication between processes. One process writes data to the pipe, and another process reads the data from the pipe. In this article, we will see how the pipe() function is used to implement the concept using C language.
About Pipe
In the pipe, the data is maintained in a FIFO order, which means writing data to one end of the pipe sequentially and reading data from another end of the pipe in the same sequential order.
If any process reads from the pipe, but no other process has not written to the pipe yet, then read returns end-of-file. If a process wants to write to a pipe, but there is no other process attached to the pipe for reading, then this is an error condition, and the pipe generates a SIGPIPE signal.
Header File
Syntax
Arguments
This function takes a single argument, an array of two integers (filedes). filedes[0] is used for reading from the pipe, and filedes[1] is used for writing to the pipe. The process which wants to read from the pipe should close filedes[1], and the process which wants to write to the pipe should close filedes[0]. If the unnecessary ends of the pipe are not explicitly closed, then end-of-file(EOF) will never be returned.
Return values
On success, the pipe() returns 0, for failure the function returns -1.
Pictorially, we can represent the pipe() function as follows:
Below are a few examples depicting how to use the pipe function in C language.
Example1
In this example, we will see how the pipe function works. Though using a pipe in a single process is not very useful, but we will get an idea.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int n;
int filedes[2];
char buffer[1025];
char *message = "Hello, World!";
pipe(filedes);
write(filedes[1], message, strlen(message));
if ((n = read ( filedes[0], buffer, 1024 ) ) >= 0) {
buffer[n] = 0; //terminate the string
printf("read %d bytes from the pipe: "%s"\n", n, buffer);
}
else
perror("read");
exit(0);
}
Here we have first created a pipe using pipe() function then written to the pipe using fildes[1] end. Then, the data has been read using the other end of the pipe, which is filedes[0]. For reading and writing to the file, we used to read() and write() functions.
Example2
In this example, we will see how parent and child processes communicate using the pipe.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main()
{
int filedes[2], nbytes;
pid_t childpid;
char string[] = "Hello, world!\n";
char readbuffer[80];
pipe(filedes);
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{
close(filedes[0]);//Child process does not need this end of the pipe
/* Send "string" through the output side of pipe */
write(filedes[1], string, (strlen(string)+1));
exit(0);
}
else
{
/* Parent process closes up output side of pipe */
close(filedes[1]);//Parent process does not need this end of the pipe
/* Read in a string from the pipe */
nbytes = read(filedes[0], readbuffer, sizeof(readbuffer));
printf("Read string: %s", readbuffer);
}
return(0);
}
First, one pipe has been created using pipe function then a child process has been forked. Then, the child process closes the read end and writes to the pipe. The parent process closes the write end and reads from the pipe and displays it. Here data flow is only one way that is from child to parent.
Conclusion:
pipe() is a powerful system call in Linux. In this article, we have seen only one-way data flow, one process writes, and another process reads, creating two pipes we can achieve bi-directional data flow also.