简体   繁体   中英

continuously communicate using named pipes between 2 processes

I've written this code which has 2 different processes in 2 different programs(present in same folder) that operates on a single named pipe. 1st program has a pointer that continuously passes thru the list. When the 'timer interrupt' is received from my another program (timer.c), the pointer has to stop and that particular list is removed.

These are my code:

ball.c

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

#define FIFO_NAME "my_fifo" /* the fifo name */

#define BUFFER_SIZE 10


struct node
{
int data;
struct node* next;
};


struct node* create_new()
{
struct node* temp = (struct node *)malloc(sizeof(struct node)*1);
return temp;
};


void populate_list(struct node **head, int players)
{
struct node *current, *temp;
int i = 1;
temp = create_new();
temp->data = i++;
temp->next = temp;
*head = temp;
while(i <= players){
    current = create_new();
    current->data = i;
    current->next = *head;
    temp->next = current;
    temp = current;
    i++;
}
}


void display_list(struct node **head)
{
if(NULL == *head)
{
     printf("the list is empty\n");
}
else
{
    struct node *temp = *head;
    while(temp->next != *head){
        printf("%d - ", temp->data);
        temp = temp->next;
    }
    printf("%d\n", temp->data);
}
}


void delete_player(struct node **pos)
{
printf("Deleting Player - '%d'\n", (*pos)->data);
struct node *temp, *ptr;
temp = ptr = *pos;
while(temp->next != *pos){
    temp = temp->next;
}
temp->next = ptr->next;
free(ptr);
*pos = temp;
}



int main(int argc, char **argv)
{
int res;
char buffer[BUFFER_SIZE + 1];
if (access(FIFO_NAME, F_OK) == -1)      /* check if fifo already exists*/
{
    res = mkfifo(FIFO_NAME, 0777); /* if not then, create the fifo*/
    if (res != 0) {
        fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
        exit(EXIT_FAILURE);
    }
}

memset(buffer, '\0', BUFFER_SIZE+1);        /* clear the string */

printf("Process %d - opening FIFO\n\n", getpid());  
res = open(FIFO_NAME, O_RDWR | O_NONBLOCK);

struct node *head = NULL;
int players;

printf("Enter the number of players: ");
scanf("%d", &players);

populate_list(&head, players);
printf("\nThe players are: \n");
display_list(&head);

printf("\n-------------------Game Started-----------------\n");

struct node *pos, *start = head;
int breakflag = 0;

while(start->next != start)
{
    while(breakflag == 0)
    {
        read(res, buffer, BUFFER_SIZE+1);
        if(strcmp(buffer, "intr") == 0){
            breakflag = 1;
            memset(buffer, '\0', BUFFER_SIZE+1);
        }
        start = start->next;
    }
    pos = start;
    start = start->next;
    printf("\nThe ball is currently with Player '%d'\n", pos->data);
    delete_player(&pos);
    display_list(&pos);
    breakflag = 0;      //Restart the passing game
}

printf("\nWinner: Player '%d'\n", start->data);
free(start);

write(res, "stop", strlen("stop")+1);

if(res != -1)
    (void)close(res); /* close the fifo */

printf("Process %d - ballpass.c - finished\n", getpid());

return 0;
}

timer.c

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

#define FIFO_NAME "my_fifo" /* the fifo name */
#define FIFO_NAME1 "my_fifo1" /* the fifo name */
#define BUFFER_SIZE 10

/* Used to generate the timer delay */
void waitFor(unsigned int secs)
{
unsigned int retTime = time(0) + secs;
while(time(0) < retTime);
}

int main()
{
int res, i, random_time;
char buffer[BUFFER_SIZE + 1];

if (access(FIFO_NAME, F_OK) == -1) { /* check if fifo already exists*/
    res = mkfifo(FIFO_NAME, 0777); /* if not then, create the fifo*/
    if (res != 0) {
        fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);
        exit(EXIT_FAILURE);
    }
}

memset(buffer, '\0', BUFFER_SIZE+1); /* clear the string */

printf("Process %d - opening FIFO\n\n", getpid());
res = open(FIFO_NAME, O_RDWR | O_NONBLOCK);

while(1)
{
    read(res, buffer, BUFFER_SIZE+1);
    if(strcmp(buffer, "stop") == 0)
        break;

    random_time = rand()%10;
    waitFor(random_time);

    write(res, "intr", strlen("intr")+1);

    printf("Process %d - Timer sent interrupt\n");
}

if (res != -1)
    (void)close(res); /* close the fifo */

printf("Process %d - timer.c - finished\n", getpid());

exit(EXIT_SUCCESS);
}

The problem is my 1st prog is not able to catch the timer properly. My timer program also never receives the "stop" that 1st prog sends. Hence there is no sync at all. Sometimes, after more than 2 'interrupts' received from timer, the 1st prog catches and removes the node.

What am I missing here??

If you're using Linux, named pipes (fifos) and also unnamed pipes (shell "|") are one-way only. If you need bidirectional communication, you need either a second named pipe, or changing to another communication tool such as a socketpair.

Also, when using pipes, it might be good to open them in blocking mode. That will ensure that both programs (client and server) go beyond the open() call only when both have engaged to the pipe. Otherwise, if the writer connects before the reader, some data might be lost (I'm not completely sure about this).

These links might be useful to know more about fifos and sockerpairs:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM