Manu
Manu

Reputation: 5784

Passing a structure through a FIFO

I have written a simple code where one process is passing a structure to another process, the parent process is writing the data, but child process is not able to access it. I have used fork() system call to create two processes. But i have problem here the parent process i called twice and child process is also called twice when i run the program. Can any one let me know what mistake i am doing.

#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <string.h>

#define MAX_LINE_LEN    100
#define FIFO_NAME "my_fifo"

typedef struct student_info  {
char *name;
int age;
char *sex;
}student;

int w_byte_parent = 0, r_byte_parent = 0;
int w_byte_child = 0, r_byte_child = 0;

void do_child() {
  int fifo;
  char buffer[MAX_LINE_LEN];
  int i = 0;
  student child;

  printf("Child opening FIFO \n");
  if( (fifo = open(FIFO_NAME, O_RDWR)) < 0 )   {
    perror("open in child failed");
    exit(EXIT_FAILURE);
  }
  printf("Child  reading  from FIFO \n");
  r_byte_child = read(fifo, child, sizeof(student));
  if(r_byte_child < 0)
    printf("Read failed by child process\n");
  printf("%d Bytes read by child process\n", r_byte_child);
  }

 int main(int argc, char **argv)  {
 int fifo;
 char buffer[MAX_LINE_LEN];
 int ch = 0, i = 0;

 /*
 ** Create a FIFO
 */
 /* Parent creating FIFO */
if( (mkfifo(FIFO_NAME, 0666)) < 0)  {
    if( errno != EEXIST ) {
        perror( "mkfifo" );
        exit( EXIT_FAILURE );
    }
}
/*
 ** Create other process 
 */

switch(fork())  {
    case -1:
        perror("fork()");
        exit(EXIT_FAILURE);
    case 0: /* Child Process */
        do_child();
        break;
    default:/* Parent Process */
        break;
}
/* Pass a structure to FIFO */
student *info;
info = (student *)malloc( sizeof (student)) ;
info->name = (char *)calloc(sizeof(char), 10);
strcpy(info->name, "jack");
info->age = 27;
info->sex = (char *)calloc(sizeof(char), 10);
strcpy(info->sex , "Male");

/* Parent Opening FIFO */
printf("parent opening FIFO \n");
if( (fifo = open(FIFO_NAME,  O_RDWR)) < 0 )   {
    perror("open in parent failed");
    exit(EXIT_FAILURE);
}

/*
 ** Write some thing into FIFO so child can read it
 */
printf("parent writing to FIFO \n");
w_byte_parent = write( fifo, info, sizeof(struct student_info));
if(w_byte_parent < 0)
    printf("Nothing was written to FIFO by parent\n");
printf("Wrote %d bytes to FIFO\n",w_byte_parent);
}

Upvotes: 2

Views: 5822

Answers (1)

Adam Rosenfield
Adam Rosenfield

Reputation: 400284

Let's start with the basics. Compiling your code with GCC with the -Wall option:

$ gcc fifo.c -o fifo -Wall
fifo.c: In function ‘do_child’:
fifo.c:33: warning: implicit declaration of function ‘read’
fifo.c:24: warning: unused variable ‘i’
fifo.c:23: warning: unused variable ‘buffer’
fifo.c: In function ‘main’:
fifo.c:48: warning: implicit declaration of function ‘mkfifo’
fifo.c:58: warning: implicit declaration of function ‘fork’
fifo.c:88: warning: implicit declaration of function ‘write’
fifo.c:42: warning: unused variable ‘i’
fifo.c:42: warning: unused variable ‘ch’
fifo.c:41: warning: unused variable ‘buffer’
fifo.c:92: warning: control reaches end of non-void function

Ignoring all of the unused variables problems, you need to include <unistd.h> and <sys/stat.h> to get proper declarations of read, mkfifo, fork, and write. Compiling again:

$ gcc fifo.c -o fifo -Wall -Wno-unused
fifo.c: In function ‘do_child’:
fifo.c:35: error: incompatible type for argument 2 of ‘read’
fifo.c: In function ‘main’:
fifo.c:94: warning: control reaches end of non-void function

You're passing a student instance as parameter 2 to read, but it expects a void* pointer. You need to pass the address of the student instance as &child. Also, it would be good to explicitly return a value form main(), although that's not strictly necessary, since failing to return a value form main() implicitly returns 0 (but only for the main() function).

But even with those errors corrected, you still see the output of the parent process twice. Why? Because both the parent and the child processes are executing the code block below the switch statement. The child process calls the do_child() function and never exits, so it returns and continues executing.

The simple fix to that is make sure to exit the child process, either at the end of do_child(), or immediately after the call returns, e.g.

Upvotes: 4

Related Questions