【问题标题】:Order of opening named pipes causing possible race condition?打开命名管道的顺序导致可能的竞争条件?
【发布时间】:2015-07-23 13:27:57
【问题描述】:

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

【问题讨论】:

  • 如果不看这两个文件中的代码就无法判断,但我猜客户端和服务器希望他们的连接握手以特定顺序发生。
  • 你正在使用阻塞openreadwrite,所以调用顺序很重要。

标签: c pipe ipc named-pipes


【解决方案1】:

来自man 7 fifo

内核为每个 FIFO 特殊文件维护一个管道对象,该文件是 由至少一个进程打开。 FIFO 必须在两端打开(读取和 写入),然后才能传递数据。通常,打开 FIFO 块直到 另一端也打开了。

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

【讨论】:

    【解决方案2】:

    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 进行写入(这将阻塞直到有人打开它进行读取)。他们中的任何一个都不能继续到将解锁另一个的行。

    【讨论】:

    • 谢谢你解释了很多。因此,第二个代码似乎成为典型的死锁案例的牺牲品。
    猜你喜欢
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 2011-12-20
    • 1970-01-01
    相关资源
    最近更新 更多