M. Chakhtoura
M. Chakhtoura

Reputation: 75

How to make parent and child bidirectional pipe in C

I am trying to do a bidirectional pipe, the parent sends n number (int) to the child and the child return them doubled. I can't figure out what's my error? I scanned the number n is the parent, sent it through fd1[1], and then proceeded to send those n numbers for the child to double. In the child, I read the number n and then for every number I read, I double and send back.

int main(){
    int pid,n,c,p,k,nbread;
    char buf1[2], buf2[2];
    int fd1[2], fd2[2];
    pipe(fd1);
    pipe(fd2);
    pid=fork();
    if(pid==0){
        close(fd1[1]);
        close(fd2[0]);
        read(fd1[0],buf2,sizeof(int));
        n = atoi(buf2);
        for(int i = 0; i<n;i++){
            nbread = read(fd1[0],buf2,sizeof(int));
            sleep(3);
            if(nbread == -1)
            exit(1);
            c = atoi(buf2);
            c = c*2;
            sprintf(buf2,"%d",c);
            write(fd2[1],buf2, sizeof(int));
        }
        close(fd1[0]);
        close(fd2[1]);
    }
    close(fd1[0]);
    close(fd2[1]);
    printf("Enter integer: ");
    scanf("%d",&p);
    sprintf(buf1,"%d",p);
    write(fd1[1],buf1,sizeof(int));
    sleep(3);
    for(int i=0;i<n;i++){
        sprintf(buf1,"%d",i);
        write(fd1[1],buf1,sizeof(int));
        read(fd2[0],buf1,sizeof(int));
        printf("number is: %s",buf1);
    }
    close(fd1[1]);
    close(fd2[0]);
    wait(NULL);
    return 0;}

Upvotes: 7

Views: 5263

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753475

Fixing the parent loop to test p and not n fixes the main problems. Making sure that the buffers are big enough is a good idea too. Writing the whole buffer is OK though not necessarily ideal.

This code works; it has more debugging output in it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    int pid, n, c, p, k, nbread;
    char buf1[12], buf2[12];
    int fd1[2], fd2[2];
    pipe(fd1);
    pipe(fd2);
    pid = fork();
    if (pid == 0)
    {
        close(fd1[1]);
        close(fd2[0]);
        read(fd1[0], buf2, sizeof(buf2));
        n = atoi(buf2);
        printf("Child read %d\n", n);
        for (int i = 0; i < n; i++)
        {
            printf("child dozes...\n");
            sleep(3);
            printf("child wakes...\n");
            nbread = read(fd1[0], buf2, sizeof(buf2));
            if (nbread == -1)
            {
                fprintf(stderr, "child exits after read failure\n");
                exit(1);
            }
            c = atoi(buf2);
            c = c * 2;
            sprintf(buf2, "%d", c);
            write(fd2[1], buf2, sizeof(buf2));
            printf("Child wrote [%s]\n", buf2);
        }
        close(fd1[0]);
        close(fd2[1]);
        printf("Child done\n");
        exit(0);
    }
    else
    {
        close(fd1[0]);
        close(fd2[1]);
        printf("Enter integer: ");
        scanf("%d", &p);
        sprintf(buf1, "%d", p);
        write(fd1[1], buf1, sizeof(buf1));
        printf("Parent wrote [%s]\n", buf1);
        printf("parent dozes...\n");
        sleep(3);
        printf("parent wakes...\n");
        for (int i = 0; i < p; i++)
        {
            sprintf(buf1, "%d", i);
            write(fd1[1], buf1, sizeof(buf1));
            printf("parent wrote [%s]\n", buf1);
            read(fd2[0], buf2, sizeof(buf2));
            printf("number is: %s\n", buf2);
        }
        close(fd1[1]);
        close(fd2[0]);
        wait(NULL);
    }
    return 0;
}

Sample output:

Enter integer: 4
Parent wrote [4]
parent dozes...
Child read 4
child dozes...
parent wakes...
parent wrote [0]
child wakes...
Child wrote [0]
child dozes...
number is: 0
parent wrote [1]
child wakes...
Child wrote [2]
child dozes...
number is: 2
parent wrote [2]
child wakes...
Child wrote [4]
child dozes...
number is: 4
parent wrote [3]
child wakes...
Child wrote [6]
Child done
number is: 6

The code puts the child code and parent code into separate if and else blocks. It doesn't detect failures in pipe() or fork() which is suboptimal. The child exit(0) is not crucial any more.

Upvotes: 5

Related Questions