Using popen() and pclose() system calls, it is fairy easy to create pipes.
Function prototype for popen()
FILE *popen ( char *command, char *type);
It will return new file stream on success and NULL on unsuccessful fork() or pipe() call.
This will call pipe() system call internally. It will executes the “command” argument within the shell.
“type” can be “r” or “w”, for “read” or “write”.
Pipe created with popen() needs to be closed using pclose().
Function prototype for pclose()
int pclose( FILE *stream );
pclose will wait on the pipe process to terminate, then closes the stream.
Simple example for popen()
#include <stdio.h>
#include <stdlib.h>
#define MAXSTRS 5
int main(void)
{
int cntr;
FILE *pipe_fp;
char *strings[MAXSTRS] = { "a", "d", "b","c", "e"};
/* Create one way pipe line with call to popen() */
if (( pipe_fp = popen("sort", "w")) == NULL)
{
perror("popen");
exit(1);
}
/* Processing loop */
for(cntr=0; cntr<MAXSTRS; cntr++)
{
fputs(strings[cntr], pipe_fp);
fputc('\n', pipe_fp);
}
/* Close the pipe */
pclose(pipe_fp);
return(0);
Notes on half-duplex pipes:
Two way pipes can be created by opening up two pipes, and properly reassigning the file descriptors in the child process.
The pipe() call must be made BEFORE a call to fork(), or the descriptors will not be inherited by the child! (same for popen()).
With half-duplex pipes, any connected processes must share a related ancestry. Since the pipe resides within the confines of the kernel, any process that is not in the ancestry for the creator of the pipe has no way of addressing it. This is not the case with named pipes (FIFOS).
Notes on half duplex pipes.
* You can create a 2 way pipes by opening 2 pipes and properly reassigning the fd’s.
* pipe() call should be made before fork() call.
* For “pipe()” there should be a ancestry process. But that is not the case in named pipes.