A pipe is a pre-defined function in C that allows one process to send data to another. With the help of a pipe, one program can read the data from another if they both have access to the pipe. The pipe function in C essentially performs the same functionality as the pipe operator in Unix-based operating systems.
Note: The
pipe()
function in C allows communication for interrelated processes, e.g parent and child process.
pipe
function work in C?Now that we have discussed the purpose of the pipe()
function in C, we will look at how it works with the help of a diagram.
The diagram shows a pipe with two ends, the "Read" and "Write" ends. Here we have two interrelated processes, parent and child, that want to send information.
If the parent wants to send information to the child, it would have to first send the data to the "Write" end of the pipe. The child process would then read the data contained in the pipe from the "Read" end.
We also see that a pipe offers only a uni-directional communication channel which means that in a single pipe, only one process can write, and the other can read. Both processes can not simultaneously read and write to the same pipe.
Note: If any process tries to read data from a empty pipe, the process becomes suspended untill something is written into the pipe.
Below, we can see the syntax for the pipe()
function that is provided by the unistd.h
C library.
int pipe (int filedes[2]);
The pipe function takes in an integer array of two elements which we named filedes
. This array contains the file descriptors for the pipes' read and write end.
To read from the pipe, we would use the array's 1st element filedes[0]
, and to write to the pipe, we would use the array's 2nd element filedes[1]
.
If the pipe function executes successfully, it returns 0
; if it fails for any reason, it returns -1
. These values can be used for error handling in C applications that use the pipe()
function.
Now that we have gone through the syntax for the pipe()
function and understand how it works, let's look at how it is used in C applications with the help of a coding example.
In the application, we created a pipe shared among two processes, a parent and a child process. The child process will first write data into the pipe, and the parent will wait for the child to finish writing. Once the child process finishes, the parent will read the data in the pipe written by the child process.
Note: We create a child process using the
fork()
system call in the application.
#include <stdio.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <sys/wait.h> int main(){ int fd[2]; if(pipe(fd) == -1){ printf("\nError: Could not create a pipe!\n"); exit(-1); } int cpid = fork(); if(cpid == -1){ printf("\nError: Could not fork!\n"); exit(-1); } if(cpid == 0){ char toSend[] = "Hello educative user! <3"; write(fd[1], toSend, strlen(toSend)); printf("\nChild: Data sent to parent!\n"); exit(0); } else{ wait(NULL); char toRecieve[BUFSIZ]; read(fd[0], toRecieve, BUFSIZ); printf("\nParent: Data from child = %s\n\n", toRecieve); exit(0); } }
When we run the code, we see that first, the child writes some data into the pipe and then prints Data sent to parent!
, after which it exits.
The parent process then reads the data that was stored in the pipe and prints it onto the console so we can see that the child wrote Hello educative user! <3
into the pipe.
Line 9: First, we create an integer array named fd
to store the file descriptors that represent the read and write end of the pipe.
Lines 11–14: Now we create a pipe using the array fd
. If the function returns -1
, we print an error message and terminate.
Line 16: To create a child process, we use the fork()
system call.
Lines 18 –21: Here, we check for errors in creating the child process.
Lines 23–28: This code block represents the code for the child process. Here, we initialize a char
array toSend
with the contents Hello educative user! <3
and then pass this data into the pipe using the write()
system call. Once completed, we print the message Child: Data sent to parent
and exit.
Lines 29–35: This code block represents the code for the parent process. The parent waits for the child to finish via the wait()
system call. It then reads the data from the parent using the read()
system call and stores it in a char
array toRecieve
. It then prints the data it received from the child and exits.
Now that we have a fundamental understanding of the pipe function, let's try to solve the quiz below and see how much we have learned.
To use the pipe()
function what library should we import?
unistd.h
stdlib.h
stdio.h
fcntl.h
Free Resources