【问题标题】:open() blocks when trying to open pipe for reading尝试打开管道进行读取时,open() 会阻塞
【发布时间】:2012-09-04 11:09:17
【问题描述】:

我有两个进程,一个服务器和一个客户端,它们应该通过管道(C++、Linux)进行通信。 服务器使用O_RDONLY 标志打开管道,客户端使用O_WRONLY 打开管道。 但是,服务器在 open 函数处阻塞,而客户端似乎运行成功(open 函数返回成功,write 函数也是如此)。

我已经读到如果设置了O_NONBLOCK 标志,读取功能将继续,但如果没有客户端连接,我不希望它继续 - 可以阻止 直到客户端连接,但在我的情况下,即使在客户端完成运行后它仍然被阻止......

你能告诉我我做错了什么吗...?

代码如下:

// Server side
int pipe;
int status, nr_read = 0;

status = mkfifo(FIFO_NAME, 0666);
if (status < 0)
{
    // If the file already exists, delete it
    unlink(FIFO_NAME);

    // Try again
    status = mkfifo(FIFO_NAME, 0666);

    if(status < 0)
    {
        printf("mkfifo error: %d\n", status);
        return status;
    }
}

pipe = open(FIFO_NAME, O_RDONLY);
printf("Never gets here...\n");
[...]
nr_read = read(pipe, my_char_array, CHAR_ARRAY_SIZE);
[...]
close(pipe);
unlink(FIFO_NAME);

它永远不会到达“printf”行...

// Client side:
int pipe, nr_sent = 0;
int status = 0;

pipe = open(FIFO_NAME, O_WRONLY);
if (pipe < 0)
{
    printf("open fifo error: %d\n", status);
    return pipe;
}

[...]
nr_sent = write(pipe, my_char_array, CHAR_ARRAY_LENGTH);
[...]
close(pipe);

编辑

我没有提到这条线 #define FIFO_NAME "MYFIFO"

...这是问题所在: 正如 Jody Hagins 所说,路径是相对路径,进程从不同文件夹启动,他们试图打开不同的文件。

【问题讨论】:

  • 客户端连接后是否会不小心重新创建了 FIFO?
  • 在调试期间,我等待服务器到达“打开”行,点击继续,然后运行客户端......所以我相信不会......
  • 你有没有检查过文件实际上是由mkfifo创建的?
  • 不是也需要在客户端创建FIFO吗?
  • @tetsuo000 不,我不这么认为...客户端应该能够通过其名称打开管道。

标签: c++ linux pipe


【解决方案1】:

在写入端完成管道之前,读取端不会完成阻塞打开。

如果您不想要此功能,则打开读取端O_NONBLOCK,并使用select 确定写入端何时建立连接并相应地处理输入。

编辑

哎呀。刚刚注意到您说即使在运行客户端之后您的服务器也没有完成打开。那很奇怪。我只是剪切/粘贴您的代码,在添加缺少的标头包含和缺少的变量/常量后,运行服务器/客户端,它们按预期运行。

服务器等待客户端,当客户端运行时,服务器完成打开并读取数据。

检查您的文件以确保您有一个实际的 FIFO。

您应该会看到如下内容:

> ls -lat /tmp/FIFO
prw-r--r-- 1 user user 0 2012-09-11 10:22 /tmp/FIFO


> stat /tmp/FIFO
  File: `/tmp/FIFO'
  Size: 0               Blocks: 0          IO Block: 4096   fifo
Device: 6802h/26626d    Inode: 186603      Links: 1
Access: (0644/prw-r--r--)  Uid: (10042/ user)   Gid: (10042/ user)
Access: 2012-09-11 10:22:48.000000000 -0400
Modify: 2012-09-11 10:22:48.000000000 -0400
Change: 2012-09-11 10:22:48.000000000 -0400

【讨论】:

  • 已解决,谢谢您的示例。我将 FIFO 从“MYFIFO”(不幸的是我没有在问题中发布的#define)重命名为“/tmp/FIFO”,如您的示例所示,现在它不再阻塞......如果open函数一定需要一个完整的路径,为什么它在尝试打开读取时阻塞而在打开写入时没有阻塞?
  • open() 不需要完整路径。但是,您必须确保客户端和服务器中的路径引用同一个文件。此外,某些文件系统不支持 FIFO 文件,但这会在创建文件时导致错误。我最好的猜测是您的服务器和客户端实际上并没有引用同一个文件(也许它们是从不同的目录运行的,并且由于它们使用的是相对文件名,因此服务器正在创建一个新的 FIFO,而客户端使用的是一个已经存在)。无论如何,很高兴能提供帮助。
  • 是的,就是这样,它们是从不同的目录运行的。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-25
  • 1970-01-01
  • 2011-12-24
  • 1970-01-01
  • 2016-08-09
相关资源
最近更新 更多