Skip to content

Instantly share code, notes, and snippets.

@zaach
Created January 19, 2009 18:53
Show Gist options
  • Save zaach/49106 to your computer and use it in GitHub Desktop.
Save zaach/49106 to your computer and use it in GitHub Desktop.
/**************************
* Pipe Example *
* *
* ls | wc > output *
* *
* Date: 09/20/07 *
* [email protected] *
***************************/
#include <sys/wait.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define STDOUT 1
#define STDIN 0
int main(void)
{
/*pid holds the process identification of the child*/
pid_t pid[2];
/*pfd = pipe file descriptor array
*status = used for waitpid */
int pfd[2],status; //pfd = pipelineFileDescriptor is an array with 2 elements.
/* ask operating system for pipe, and place read end of pipe in pfd[0] and write end into pfd[1]*/
pipe(pfd); //pfd[1] (the ls) becomes the opening of the pipe and pfd[0] (the wc) becomes the outside of the pipe
/*1st fork for "ls"*/
pid[0] = fork();
/*check if the pid returned from fork is 0 (for the child), or > 0 (for the parent)*/
if(pid[0] == 0)
{
/*We are in the child process*/
/*first we need to close the read end of the pipe ("ls" isn't reading from anywhere)*/
close(pfd[0]);
/*next we need to redirect the STDOUT of "ls" to go to the pipe instead of going to the screen (default)*/
dup2(pfd[1], STDOUT); //dup2 is like mapping signals, here we are mapping stdout to pfd[1] (the ls)
/*now we must release the pipe, it is already bound with STDOUT --> why? Because child will
*soon be overwritten when execlp is called!*/
close(pfd[1]);//must close after you do the dup2()
/*Before calling exec* make sure to have closed both ends of pfd (i.e. close(fd[0]),close(fd[1])), and file descriptors*/
execlp("ls","ls",NULL);
}
else
{
/*We are in the parent process*/
/*Now, we should wait for all the data to be written to the pipe*/
waitpid(pid[0], &status, WUNTRACED | WCONTINUED); //wait(NULL) is also okay here
/*Need to fork again for "wc"*/
pid[1] = fork();
/*check if the pid returned from fork is 0 (for the child), or > 0 (for the parent)*/
if(pid[1] == 0)
{
/*we're now in our 2nd child process for "wc"*/
close(pfd[1]);
/*next we need to redirect the STDIN of "wc" to come from the pipe instead of the keyboard (default)*/
dup2(pfd[0], STDIN); //mapping STDIN to pfd[0]
/*now we must release the pipe, it is already bound with STDIN --> why? Because child will
*soon be overwritten when execlp is called!*/
close(pfd[0]);
/*Now lets redirect the output of "wc" to a file called "outfile"*/
int fildes = open("outfile", O_WRONLY|O_CREAT, 0666);
/*Again, redirect STDOUT, but this time to the file descriptor*/
dup2(fildes,STDOUT); /* copy fildes to 1 */
/*And again, before calling execlp, release this resource*/
close(fildes); /* conserve file descriptors by closing excess one */
/*Before calling exec* make sure to have closed both ends of pfd (i.e. close(fd[0]),close(fd[1])), and another file descriptors*/
execlp("wc","wc","-l",NULL);
}
else
{
/*Also, the parent needs to release the pipe, otherwise you'll face troubles!*/
close(pfd[0]);
close(pfd[1]);
/*Now wait until the second process has finished*/
waitpid(pid[1], &status, WUNTRACED | WCONTINUED);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment