Search code examples
clinuxpipecommunicationfgets

2 way comm using pipes in C linux


I want parent and child processes to communicate in C linux using pipes. First I want parent to pass a string and then child to acknowledge it. I have created two file descriptors. one for parent to child i.e. readpipe and other writepipe for viceversa. The problem is its not taking my data as input. Also I want the printf statements such as "Enter your data" to be printed once but since after fork, there are two processes so they are being displayed twice. Any alternative to that??

 //readpipe[0] = child read
 //readpipe[1]= parent write

//writepipe[0]=parent read
//writepipe[1]=child write

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

 int main(void)
 {
      pid_t pid;
      int r;
      /* Hope this is big enough. */
     char buf[1024];
     char cp[50];
     char ans;
     int readpipe[2];
     int writepipe[2];
     int a;
     int b;
     a=pipe(readpipe);
     b=pipe(writepipe);
     if (a == -1) { perror("pipe"); exit(EXIT_FAILURE); }
     if (b == -1) { perror("pipe"); exit(EXIT_FAILURE); }

     printf("\nSEND SOMETHING TO CHILD PROCESS\t");
     scanf(" %c",&ans);
     pid=fork();
     if(pid==-1)
     {
         printf("pid:main");
         exit(1);
     }

     while(ans=='y' || ans=='Y')
     {
        printf("\nEnter data\t"); //printed twice
        fgets(cp, 50, stdin);     //not taking data
        printf("\n%s",cp);        
        if(pid==0)
        { //CHILD PROCESS
         close(readpipe[1]);
         close(writepipe[0]);
         read(readpipe[0],buf,sizeof(buf));
         printf("\nSENT\n %s",buf);
         write(writepipe[1],cp,strlen(cp)+1);
       }
      else
      { //PARENT PROCESS
        close(readpipe[0]);
        close(writepipe[1]);
        write(readpipe[1],cp,strlen(cp)+1);
        read(writepipe[0],buf,sizeof(buf));
        printf("\nRECEIVED\n %s",buf);
     }
     printf("\nSEND SOMETHING TO CHILD PROCESS\t");
     scanf(" %c",&ans);
  }
  close(readpipe[1]);
  close(writepipe[0]);
  close(readpipe[0]);
  close(writepipe[1]);

   return 0;
}

Solution

    1. Why fgets is not taking data ? In the first scanf you are reading the single character and the new line will still be in
      input buffer so this will make to skip

      To solve this you should use scanf("%[^\n]%*c",&ans) - Refer this for more details

    2. Find the modified code.. it might be helpful to you ( to break from the while i made some changes and i verified the basic function)

    int main(void) {

    pid_t pid;
    int r;
    /* Hope this is big enough. */
    char buf[1024];
    char cp[50];
    char ans;
    int readpipe[2];
    int writepipe[2];
    int a;
    int b;
    a=pipe(readpipe);
    b=pipe(writepipe);
    if (a == -1) { perror("pipe"); exit(EXIT_FAILURE); }
    if (b == -1) { perror("pipe"); exit(EXIT_FAILURE); }
    
    printf("\nSEND SOMETHING TO CHILD PROCESS\t");
    scanf("%[^\n]%*c",&ans);
    //ans = getchar();
    fflush(stdin);
    pid=fork();
    if(pid==-1)
    {
        printf("pid:main");
        exit(1);
    }
    
    while(ans=='y' || ans=='Y')
    {
        if(pid==0)
        { 
            //CHILD PROCESS
            close(readpipe[1]);
            close(writepipe[0]);
            if(read(readpipe[0],buf,sizeof(buf)) < 0)
            {
                break;
            }
    
            printf("\nChild Process Read: %s\n",buf);
    
            printf("\n(child)Enter data:\t"); //printed twice
            fgets(cp, 50, stdin);     //not taking data
            printf("\nData Written to Parent%s",cp);
            if(!strncmp("Q",cp,1) || write(writepipe[1],cp,strlen(cp)+1) < 0)
            {
                break;
            }
        }
        else
        { 
            //PARENT PROCESS
            close(readpipe[0]);
            close(writepipe[1]);
            printf("\n(Parent)Enter data\t"); //printed twice
            fgets(cp, 50, stdin);     //not taking data
    
            printf("\nData Writtent to Child: %s",cp);
            if(!strncmp("Q",cp,1) || write(readpipe[1],cp,strlen(cp)+1) < 0)
            {
                break;
            }        
    
            if(read(writepipe[0],buf,sizeof(buf)) < 0)
            {
                break;
            }
            printf("\nParent Process Read: %s\n",buf);
        }
        ans ='y';
    }
    
    close(readpipe[1]);
    close(writepipe[0]);
    close(readpipe[0]);
    close(writepipe[1]);
    return 0;
    

    }