ziberteck
ziberteck

Reputation: 13

Sending data between a parent and child using pipe in c

Okay so I've been trying to tinker with this code that would send data a value from the parent process to the child process, the child process then squares it and returns the value back to the parent. TLDR, this is a practice assignment for using pipe. I've been able to find examples that demonstrate this functionality using two pipes. But I was wondering if it was possible to do this with only one pipe.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>

int int_pow(int base, int exp){
    int sum = base;
    for(int i = 1; i<exp; i++){
        sum = sum * base;
    }
    return sum;
}

int main(){
    int fd[2]; //0 = read, 1 = write
    pid_t pid;
    if(pipe(fd) < 0){
        printf("Error:  could not create pipe.\n");
        exit(1);
    }

    if ((pid = fork()) < 0){
        printf("Error:  could not create child.\n");
        exit(1);
    }
    printf("\n");
    //child process
    if (pid == 0){
        printf("hello from child.\n");
        int random = 0;
        int waiting = 0;
        waiting = read(fd[0], &random, sizeof(random)+1);
        printf("%d\n", random);

        random = int_pow(random,2);
        write(fd[1], &random, sizeof(random)+1);

    } else {
        printf("hello from parent.\n");
        int random = rand()%100+1;
        printf("%d\n", random);
        write(fd[1], &random, sizeof(random));
        int waiting = 0;
        waiting = read(fd[0], &random, sizeof(random)+1);
        printf("%d\n", random);
    }
    close(fd[0]); //close parent read process
    close(fd[1]); //close parent write process
    return 0;
}

UPDATE: I managed to get the result I was after. I was trying to make it a lot more complicated than needed.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

int int_pow(int n, int exp){
    int sum = n;
    for (int i = 1; i < exp; i++){
        sum = sum * n;
    }
    return sum;
}

int main()
{
    int random = 0;
    pid_t fpid;
    int p[2]; // 0 = read, 1 = write

    if (pipe(p) < 0){
        exit(1);
    }

    fpid = fork();

    if (fpid == 0){

        printf("\n(Child) Hello from child. \n");
        read(p[0], &random, sizeof(random));
        printf("(Child) Recieved from parent: %d \n", random);
        random = int_pow(random, 2);
        printf("(Child) Sent from child: %d \n", random);
        write(p[1], &random, sizeof(random));

        close(p[0]);//close child read.
        close(p[1]);//close child write.

        exit(0);
    } else {
        //wait(NULL);
        printf("(Parent) Hello from parent. \n");

        random = rand()%100+1;
        printf("(Parent) Sent from parent: %d \n", random);
        write(p[1], &random, sizeof(random));
        sleep(1);
        int wait = read(p[0], &random, sizeof(random));

        close(p[0]);//close parent read.
        close(p[1]);//close parent write.


        printf("(Parent) Recieved from Child: %d \n", random);
        exit(0);
    }
    return 0;
}

Upvotes: 0

Views: 189

Answers (3)

ziberteck
ziberteck

Reputation: 13

I was able to figure out how to do this.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>

int int_pow(int n, int exp){
    int sum = n;
    for (int i = 1; i < exp; i++){
        sum = sum * n;
    }
    return sum;
}

int main()
{
    int random = 0;
    pid_t fpid;
    int p[2]; // 0 = read, 1 = write

    if (pipe(p) < 0){
        exit(1);
    }

    fpid = fork();

    if (fpid == 0){

        printf("\n(Child) Hello from child. \n");
        read(p[0], &random, sizeof(random));
        printf("(Child) Recieved from parent: %d \n", random);
        random = int_pow(random, 2);
        printf("(Child) Sent from child: %d \n", random);
        write(p[1], &random, sizeof(random));

        close(p[0]);//close child read.
        close(p[1]);//close child write.

        exit(0);
    } else {
        //wait(NULL);
        printf("(Parent) Hello from parent. \n");

        random = rand()%100+1;
        printf("(Parent) Sent from parent: %d \n", random);
        write(p[1], &random, sizeof(random));
        sleep(1);
        int wait = read(p[0], &random, sizeof(random));

        close(p[0]);//close parent read.
        close(p[1]);//close parent write.


        printf("(Parent) Recieved from Child: %d \n", random);
        exit(0);
    }
    return 0;
}

Upvotes: 1

KL-Yang
KL-Yang

Reputation: 401

If you are using Linux alike, just type

man 2 pipe

You will have a working example very similar as your code. Or follow this link http://man7.org/linux/man-pages/man2/pipe.2.html.

By comparing them, you can find where your have misunderstanding.

Pipe can only read once, think it as a water pipe, not like a regular file, though also use a file descriptor. For example, in water pipe, you put in 1 liter at one end, and will only get out 1 liter at the other end. As many comments said, the read in parent consumed that 1 liter water so the child process never get a chance to have them.

Upvotes: 0

ensc
ensc

Reputation: 6994

no; your code will not work because the parent process can consume the data written by him.

E.g.

parent              child
--------------------------
write()
read()
                    read() --> blocks

You can simulate this e.g by placing a sleep(5) before the child read().

You will need other synchronization ways; e.g. kill(getpid(), SIGSTOP) in the parent after the write() and kill(getppid(), SIGCONT) in the child after read().

Upvotes: 0

Related Questions