【问题标题】:Can't read from multiple fifos无法从多个 fifo 读取
【发布时间】:2016-01-12 14:48:17
【问题描述】:

我在尝试读取多个 fifo 时遇到了一个非常烦人的问题。我有 1 个进程等待来自 fifo 的结构,并且很少有进程向他发送这些结构的信号。第一次阅读后,我无法从任何信号中读取更多内容。看起来程序冻结了。

发送进程在 main 中有这个

myfifo = '/tmp/myfifo{0}' //{0} is a number that every process has individual.
mkfifo(myfifo, 0666);
fd = open(myfifo, O_WRONLY);
write(fd, &demon1 , sizeof(demon1));
close(fd);
while (1)
{
}

这在 signal_handler 中

void signal_handler(int signum)
{
    if (signum == SIGUSR1)
    {
        //some declarations here
        mkfifo(myfifo, 0666);
        fd = open(myfifo, O_WRONLY | O_NONBLOCK);
        write(fd, &demon1 , sizeof(demon1));
    }
}

虽然阅读过程有

myfifo[i] = /tmp/myfifo{0} // {0} is i which is the number of process that sends.

 while(1)
 {
    for(i=0;i<n;i++)
    {
       fd = open(myfifo[i], O_RDONLY | O_NONBLOCK);
       r = read(fd, &demon1, sizeof(demon1));
       if(r > 1)
       {
           //printf struct elements
       }

    }
  }

【问题讨论】:

  • 请发送一个最小的工作示例。例如,您是否在读取过程中打开后再次关闭每个fd?否则你很快就会用完文件描述符
  • 这在很大程度上是其他东西正在打印和设置目录的所有内容。
  • 我建议阅读man 7 fifo的输出,特别是关于在非阻塞模式下打开FIFO的部分。我认为当 FIFO 的另一端未打开时,您的只写、非阻塞 opens 将失败并显示 errno ENXIO

标签: c linux named-pipes


【解决方案1】:

您打开循环内的管道。这样一来,您很快就会用完文件描述符(如果您检查了open() 的结果是否有错误,您会看到)。

我建议打开循环外的所有 FIFO,将文件描述符存储在一个数组中,然后读取它们中的每一个,但是……读取会阻塞。请参阅select(2) 找出哪个 FIFO 有数据。

另一种解决方案是单个 FIFO,写入过程应在消息中发送它的 ID。这样,主进程只需要监听一个 FIFO。如果它想知道是谁发送的消息,它可以查看消息中的 ID。这里的问题:您需要某种锁定,否则多个进程将同时写入 FIFO,并且它们的数据可能混淆(这取决于 FIFO 缓冲区)。

【讨论】:

    【解决方案2】:

    打开阅读后不要关闭文件描述符:

    while(1)
    {
        for(i=0;i<n;i++)
        {
           fd = open(myfifo[i], O_RDONLY | O_NONBLOCK);
           r = read(fd, &demon1, sizeof(demon1));
           if(r > 1)
           {
               //printf struct elements
           }
    

    这里缺少close(fd)

        }
    }
    

    由于打开是非阻塞的,很快就会达到每个进程的最大 fd 数,后续打开会失败。

    【讨论】:

    • 这仍然没有帮助,如果我不发送到 myfifo[0] 其他 fifo 将不会被读取
    • @Thomas 对不起,我不明白这个评论,你能详细说明会发生什么吗?
    • myfifo[0] 有第一个 fifo 的路径,如果我不读取它,我不会检查下一个。例如,如果我首先发送到 myfifo[2](第三条路径),它将等到 myfifo[0] 和 myfifo[1] 被读取。
    • @Thomas 据我所知,原因超出了您提供的代码 sn-ps 的范围。或者你可能误解了你所看到的。我只能建议您,提供一个可以实际编译和测试的最小示例。
    • 我想我通过删除管道找到了解决办法。虽然我对结果并不满意。会看看情况如何。我稍后会提供我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-01
    相关资源
    最近更新 更多