在两个进程之间使用命名管道持续通信

时间:2016-06-30 11:02:42

标签: c linux named-pipes

我编写了这段代码,它在2个不同的程序(存在于同一文件夹中)中有2个不同的进程,这些程序在一个命名管道上运行。 第一个程序有一个指针连续通过列表。当从我的另一个程序(timer.c)收到'timer interrupt'时,指针必须停止并且删除该特定列表。

这些是我的代码:

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);
}

问题是我的第一个编程无法正确捕捉计时器。我的计时器程序也从未收到第一个编程发送的“停止”。因此根本没有同步。 有时,在从计时器收到超过2个'中断'之后,第1个prog会捕获并移除节点。

我在这里缺少什么?

1 个答案:

答案 0 :(得分:1)

如果您使用的是Linux,则命名管道(fifos)和未命名的管道(shell“|”)仅为单向。如果需要双向通信,则需要第二个命名管道,或者更改为另一个通信工具,例如socketpair。

此外,使用管道时,最好在阻塞模式下打开它们。这将确保两个程序(客户端和服务器)仅在两者都已连接到管道时超出open()调用。否则,如果编写者在读者之前连接,一些数据可能会丢失(我对此并不完全确定)。

这些链接可能有助于了解有关fifos和sockerpairs的更多信息: