tags:

views:

62

answers:

2

The attached code should allow the communication between 2 terminals. The communication is made through 2 FIFO, which are created in the current directory. The program has to open the 2 fifos and the son reads from STDIN and puts on the fifo1 and the father reads from the other fifo and prints on terminal. In this way the communication takes place since the call to the program is: ./myprog fifo1 fifo2 (for the first terminal) and ./myprog fifo2 fifo1 (for the second terminal). The code does not work well, I suspect that the child write() performs on the fifo does not work well. Hoping that I explained well, help meeee :'(

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <poll.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>

int main(int argc,char* argv[])
{
    if(argc<3)
    {
        printf("Error: Too few arguments...\n");
        exit(-1);
    }

    char** buffer_in=(char**) malloc(sizeof(char*));
    char** buffer_out=(char**) malloc(sizeof(char*));
    size_t dim_buff=sizeof(char*);
    FILE* stream;
    FILE* input;
    int fifo_in, fifo_out, num_poll_c, num_poll_f, read_count, i,write_b;
    pid_t pid;
    ssize_t length;
    struct pollfd* fd_set_c=(struct pollfd*) malloc(sizeof(int));//for the child
    struct pollfd* fd_set_f=(struct pollfd*) malloc(sizeof(int));//for the father


    printf("Write character e press enter:\n");

    if((fifo_in=open(argv[1],O_RDWR|O_NONBLOCK))==-1)
        perror("error open");
    if((fifo_out=open(argv[2],O_RDWR|O_NONBLOCK))==-1)
        perror("error open");

    if((input=fdopen(STDIN_FILENO,"r"))==NULL)
        perror("error fdopen");


    if((pid=fork())==-1)
        perror("error fork");
    while(1)
    {   
        if(pid==0)  /*child*/   
        {   
            fd_set_c->fd=STDIN_FILENO;
            fd_set_c->events=POLLIN;
            if((num_poll_c=poll(fd_set_c, 1, -1))==-1)
                perror("error poll child");//poll on fifo_in
            if((length=getline(buffer_in,&dim_buff,input))==-1)
                perror("error getline");



                printf("The written word is::%s\n",*buffer_in);/*my control for see what in buffer_in is*/


            if((write_b=write(fifo_in,*buffer_in,dim_buff))==-1)
                perror("error write");

        }

        else    /*father*/
        {   
            fd_set_f->fd=fifo_out;
            fd_set_c->events=POLLIN;

            if((num_poll_f=poll(fd_set_f, 1, 5000))==-1)
                perror("error poll father");//poll on fifo_out      
            if((read_count=read(fifo_out,*buffer_out,SSIZE_MAX))==-1)
                perror("error read");//read on fifo_out
            for(i=0;i<=read_count;i++)
                printf("%s",buffer_out[i]);//print on stdout buffer_out


        }
    }
    return 0;   

}
+2  A: 

You should use pipes(man 2 pipe. or shared memory: man shmget) for communication between your processes and a semaphore to protect reads/writes. Look for "producer/consumer" on google.

take a look at this: http://users.evtek.fi/~tk/rtp/sem-producer-consumer.c and this: http://knol.google.com/k/producer-consumer-problem#

Mat
Mmm...I am a bit puzzled by your answer:1-this is not normal pipe but named pipe (man 3 mkfifo)2-The data is protected by poll(man 2 poll)3-I don't think that I have to create shared memory for the FIFO! Or not?
Andrea
A: 

You have a mess here.

Parent might block in read() from FIFO because there are still open writable file descriptors for it. And the open writable file descriptor belongs to the parent process itself. And since it is blocked in the read() it can't write into it.

Put opening of FIFOs after fork(). Open in a stricter mode: either only for writing or only for reading, not wildcard O_RDWR. That way you would mirror the logic generally applied to pipe()s.

Additionally, poll()ing on STDIN_FILENO is dangerous, as stdio is buffered. File descriptor might have nothing to read - because it was all already read out before, but is inside the stdio buffer. If you really sure you know what you do, at least try to disable buffering, man setvbuf. But I still wouldn't do it in the presence of fork(): buffered data might be read twice: once by child and once by parent.

Dummy00001