简体   繁体   中英

Passing data from a parent to a child and back with Unix C

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;
}

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 { //...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM