打开命名管道的顺序导致可能的竞争条件?

时间:2015-05-12 15:08:01

标签: c pipe ipc named-pipes

我正在尝试使用IPC通过命名管道在两个进程之间创建一个非常基本的客户端服务器通信。

我有2个管道,即fifo_clientfifo_server

我有以下两个类fifoclient.cfifoserver.c,它们具有以下代码行来打开这两个管道。

fifoclient.c

int client = open("fifo_client",O_WRONLY);
int server = open("fifo_server",O_RDONLY);

fifoserver.c

int client = open("fifo_client",O_RDONLY);
int server = open("fifo_server",O_WRONLY);

但是,只需更改在client中打开serverfifoserver.c管道的顺序,该程序就会冻结。

这是代码在冻结时的编写方式:

fifoserver.c

int server = open("fifo_server",O_WRONLY);
int client = open("fifo_client",O_RDONLY);

请注意,在这种情况下,server管道在client管道之前打开。这导致程序没有响应(可能的竞争条件?)。

有人可以解释发生了什么以及为什么?

编辑:

以下是两个类的完整代码:

fifoserver.c

#define BUFSIZE 20
#include<stdio.h>
#include<fcntl.h>
int main()
{

    char buf[BUFSIZE];
    int client = open("fifo_client",O_RDONLY);
    int server = open("fifo_server",O_WRONLY);
    if( server<0 || client < 0)
    {
        printf("Couldn't open file\n");
        exit(1);
    }

    read(client,buf,BUFSIZE*sizeof(char));
    printf("Client Says: %s\n",buf);
    write(server,"Fine, Thank You!",BUFSIZE*sizeof(char));
    close(server);
    close(client);      
    return 0;
}    

fifoclient.c

#define BUFSIZE 20
#include<stdio.h>
#include<fcntl.h>
int main()
{
    char buf[BUFSIZE];
    int client = open("fifo_client",O_WRONLY);
    int server = open("fifo_server",O_RDONLY);
    if(client <0 || server <0)
    {
         printf("ERROR! Couldn't open file!\n");
         exit(1);
    }
    write(client,"Hello! How are you?",BUFSIZE*sizeof(char));
    read(server,buf,BUFSIZE*sizeof(char));
    printf("Server Says: %s\n",buf);
    close(server);
    close(client);
    return 0;
}

2 个答案:

答案 0 :(得分:3)

  

fifoclient.c

int client = open("fifo_client",O_WRONLY);

客户端打开将阻塞,直到打开FIFO进行读取。

  

fifoserver.c

int client = open("fifo_client",O_RDONLY);

在服务器中,这个打开将取消阻止客户端中的先前打开。

现在,当您将服务器中的行交换为

int server = open("fifo_server",O_WRONLY);
int client = open("fifo_client",O_RDONLY);

客户端被阻止打开客户端FIFO,但服务器正在尝试打开服务器FIFO进行写入(这将阻塞,直到有人打开它进行读取)。他们都没有能够进入能够解除对方阻挡的线路。

答案 1 :(得分:3)

来自man 7 fifo

  

内核为每个FIFO特殊文件维护一个管道对象   由至少一个过程打开。必须在两端打开FIFO(读取和   在传递数据之前。通常,打开FIFO块直到   另一端也开了。

换句话说,您的open()调用将阻塞,直到管道另一端有进程。这不是竞争条件 - 相反,它是一个僵局。如果进程没有以相同的顺序打开管道,它们将永远等待彼此。因此,正如您所注意到的,解决方案是他们必须以相同的顺序打开fifos。