【问题标题】:Unable to open FIFO for writing无法打开 FIFO 进行写入
【发布时间】:2013-05-06 05:19:09
【问题描述】:

“服务器”程序端:

#define RESP_FIFO_NAME "response"

/* Global Variables */
char *cmdfifo = CMD_FIFO_NAME; /* Name of command FIFO. */
char *respfifo = RESP_FIFO_NAME; /* Name of response FIFO. */

int main(int argc, char* argv[]) {
int infd, outfd; /* FIFO file descriptors. */

... // blah blah other code here

/* Create command FIFO. */
if (mkfifo(cmdfifo, FIFO_MODE) == -1) {
    if (errno != EEXIST) {
        fprintf(stderr, "Server: Couldn’t create %s FIFO.\n", CMD_FIFO_NAME);
        exit(1);
    }
}

/* Create response FIFO. */
if (mkfifo(respfifo, FIFO_MODE) == -1) {
    if (errno != EEXIST) {
        fprintf(stderr, "Server: Couldn’t create %s FIFO.\n", RESP_FIFO_NAME);
        exit(1);
    }
}
/* Open the command FIFO for non-blocking reading. */
if ((infd = open(cmdfifo, O_RDONLY | O_NONBLOCK)) == -1) {
    fprintf(stderr, "Server: Failed to open %s FIFO.\n", CMD_FIFO_NAME);
    exit(1);
}

        /* Open the response FIFO for non-blocking writes. */
if ((outfd = open(respfifo, O_WRONLY | O_NONBLOCK)) == -1) {
            fprintf(stderr, "Server: Failed to open %s FIFO.\n", RESP_FIFO_NAME);
            perror(RESP_FIFO_NAME);
            exit(1);
        }

程序打印输出:

Server: Couldn’t create response FIFO.

我对 FIFO 知之甚少,因为我的教授没有教它。这就是我通过阅读他的例子和讲义所能做到的。我试过没有 O_NONBLOCK 标志,但这只会导致程序挂起,所以它是必需的。不明白为什么读FIFO没问题,写FIFO打不开。

【问题讨论】:

  • 您应该在错误消息中报告mkfifo() 调用中使用的名称——所以respfifo 而不是RESP_FIFO_NAME。当前目录(程序运行时的)中存在哪些 FIFO?您确定要在 FIFO 名称中包含尖括号(还是来自不同版本代码的错误消息)?您可以在输出中包含errno 和strerror(errno);这将有助于诊断问题所在(EEXIST vs EPERM vs ...)。
  • 使用perror 或strerror 了解确切的错误。
  • RESP_FIFO_NAME 是一个预处理器 #define'd 宏常量。我现在补充一下。我认为这并不重要,因为它只是一个带有直接文本替换的字符串文字。是的,我现在就用 perror 看看实际的问题是什么。
  • perror(RESP_FIFO_NAME) 输出 <RESP_FIFO_NAME>: No such device or address 显然是 ENXIO
  • 有趣:在 Mac OS X 上,ENODEV 未列为来自mkfifo(2) 的可能错误。您是否执行过任何chdir() 操作?我看到删除尖括号不会改变结果。 FIFO_MODE 是什么?命令FIFO是否已经存在?

标签: c unix file-io fifo mkfifo


【解决方案1】:

来自手册页:

进程可以在非阻塞模式下打开 FIFO。在这种情况下,打开 即使没有人在写入端打开 for read only 也会成功 然而;打开只写会因 ENXIO 失败(没有这样的设备或 地址)除非另一端已经打开。

你应该在“客户端”中打开这个。

【讨论】:

  • 好的。当时我对他的指示感到困惑,因为他说:/* Create and appropriately open the command and reply FIFOs. */ 这是在创建虚假“客户”(子)进程的进程分叉之前。我在客户端进程中打开了它,但后来在程序中发生了......
  • 这很有趣——但会影响打开 FIFO,而不是创建它,这显然是问题所在。 @ICantNameMe:你确定是你的mkfifo() 失败了吗?您是否在不更改消息的情况下复制并粘贴了错误消息块?
  • 失败的不是mkfifo,而是O_WRONLY | O_NONBLOCK 的open 命令给了我一个ENXIO: no such device or address error。我不知道为什么它给了我这个错误,因为我还不能访问客户端文件,所以我想这意味着我必须在程序中将它进一步向下移动,直到分叉之后,否则没有人可以阅读我的内容我在写作吗?
  • 我也是这么想的,这就是为什么你必须在客户端打开这个fifo,我猜。
  • @ICantNameMe:如果是 open()(您没有显示)失败,那么您的代码 sn-p 将完全令人困惑——这需要投反对票。 Thomas 发现的错误消息的描述完全适合使用 O_NONBLOCK 打开 FIFO 进行只写。也许您应该等待打开响应 FIFO 进行写入,直到您有一个客户端使用命令 FIFO open for write?或者也许你不想要 O_NONBLOCK...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多