Reputation: 11
I am very new to C and am trying to learn how to use pipes to transfer data from a parent process to a child process and vice versa in a Unix environment. In the code below, I receive a command line argument and build a char array based on the argument's value. I then use pipes to pass the char array to a child which will execute a program called vc. This program returns a number result based on the char array. My question is how can I use a second pipe to get the result back to the parent? Also, once the parent has it, how can I print it to the screen since the parent is set to send output to the child? Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc,char *argv[])
{
int
pfildes[2],
pid,
argNumber;
char
buffer[256],
charString[1024];
//Check for arguments
if(argc != 2) {
printf("No command line arguements given.\n");
argNumber=10; //default
}
else
argNumber=atoi(argv[1]);
//***********************************
//Build charString based on argNumber
//***********************************
//create pipes
if(pipe(pfildes) == -1) {
//error occured when creating pipe
perror("demo");
exit(1);
}
//create child process
if((pid=fork()) < 0) {
//error occured when forking child
perror("demo");
exit(1);
}
else if(pid > 0) {
//parent process
close(pfildes[0]);
dup2(pfildes[1],1);
printf("%s", charString);
close(pfildes[1]);
perror("demo");
_exit(1);
}
else {
//child process
close(pfildes[1]);
dup2(pfildes[0],0);
execlp("/usr/bin/vc","vc", NULL);
close(pfildes[0]);
perror("demo");
exit(1);
}
while(wait(NULL) >0);
return 0;
}
Upvotes: 1
Views: 1652
Reputation: 70492
You can use socketpair()
instead of pipe()
to generate a bidirectional communication channel between the parent and child process:
//...
if (socketpair(PF_UNIX, SOCK_STREAM, 0, pfildes) == -1) {
//error occured when socket pair
perror("demo: socketpair");
exit(1);
}
//..
In the child process, you can dup()
one of the pair into both input and output before calling exec()
:
//...
else {
//child process
close(pfildes[1]);
dup2(pfildes[0],0);
dup2(pfildes[0],1);
dup2(pfildes[0],2);
close(pfildes[0]);
execlp("/usr/bin/vc","vc", NULL);
perror("demo: child exec");
exit(1);
}
//...
In the parent process, you can create a FILE *
from a file descriptor using fdopen()
, so you don't need to dup()
over your existing stdout
file descriptor:
//...
else if(pid > 0) {
//parent process
close(pfildes[0]);
FILE *to_child = fdopen(dup(pfildes[1]), "w");
FILE *from_child = fdopen(dup(pfildes[1]), "r");
close(pfildes[1]);
fprintf(to_child, "%s", charString);
while (fgets(buf, sizeof(buf), from_child) != NULL) {
//...do something with output
}
//...
} else { //...
Upvotes: 1