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

Order of opening named pipes causing possible race condition?

我正在尝试通过命名管道使用 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);

但是,在 fifoserver.c 中简单地改变打开 clientserver 管道的顺序,程序就会冻结。

冻结时代码是这样写的:

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

fifoclient.c

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

客户端中的这个open会阻塞,直到打开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 进行写入(这将被阻止,直到有人打开它进行读取)。 None 他们可以继续到将解锁另一个的行。

来自man 7 fifo

The kernel maintains exactly one pipe object for each FIFO special file that is opened by at least one process. The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.

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