0

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;
}
user3436838
  • 113
  • 3
  • 14
  • If you don't multiplex with e.g. [poll(2)](http://man7.org/linux/man-pages/man2/poll.2.html) you risk a deadlock with mutual starvation (each process blocked waiting some output from the other). – Basile Starynkevitch Mar 19 '14 at 12:43

2 Answers2

1

You call

    printf("\nEnter data\t"); //printed twice
    fgets(cp, 50, stdin);     //not taking data

before you check whether you are in the parent or the child processes. That of course causes both processes to print and both to read form standard input. So it's not clear which process reads the date you're typing.

The same problems would occur in these lines:

 printf("\nSEND SOMETHING TO CHILD PROCESS\t");
 scanf(" %c",&ans);

I would suggest you redesign your program to clearly seperate code that runs in the parent process afrer fork() and code that runs in the child process.

Ingo Leonhardt
  • 9,435
  • 2
  • 24
  • 33
0
  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;

}

Community
  • 1
  • 1
M Thotiger
  • 344
  • 1
  • 7
  • thanks sir. But could you please tell me a bit about the function strncmp. what's that "Q" in the program and why have you used it here? – user3436838 Mar 20 '14 at 05:54
  • I have added this logic to break from the while loop, If you enter Q. then strncmp will pass and it will break the while loop and it will exits the program.. If it is not clean.. you can choose some better way.. – M Thotiger Mar 20 '14 at 06:02