在select的非阻塞模式下使用fifo open [英] Using fifo open in non-blocking mode with select

查看:252
本文介绍了在select的非阻塞模式下使用fifo open的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个进程A和B.通信流始终是A-> B,但是我需要使用命名管道来完成它,因为我必须在B进程内部的select调用中使用管道文件描述符,并且当任何一个或两个进程退出时,写入管道的数据必须保留.

I have two processes A and B. The communication flow is always A -> B, but I need to do it using a named pipe, because I must use the pipe file descriptor in a select call inside the B process, and the data written to the pipe must persist when any or both of the processes exit.

管道在两端均以非阻塞模式打开.在过程A:

The pipe is opened in non-blocking mode on both ends. In process A:

int push_fifo_fd = open(FIFO_NAME, O_WRONLY | O_NONBLOCK | O_CREAT, 0644);

在过程B中:

int fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK | O_CREAT, 0644);

Q1. 进程B使用curl多重接口,因此我得到curl多重句柄的fd_sets并将"fd"描述符添加到读取的fd_set中,而不是进行选择调用,以获取可用于读取和写入的文件描述符.在每次select调用中,结果读取fd_set中都包含"fd",即使打开了写入端,读取仍返回0.这导致进程B使用100%的处理器时间.我提到我不知道打开管子末端的顺序.来自B的相关代码:

Q1. The process B uses curl multi interface, so I get the fd_sets of the curl multi handle and add the "fd" descriptor to the read fd_set, than make a call to select, to get the file descriptors available for reads and writes. In every call to select, "fd" is contained in the result read fd_set, but read returns 0, even if the write end is opened. This causes the process B to use 100% of processor time. I mention that I don't know to order in which the ends of the pipe are opened. The relevant code from B:

while (1)
{
    fd_set read_fds, write_fds, err_fds;

    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);
    FD_ZERO(&err_fds);

    FD_SET(fifo_fd, &read_fds);
    // some code
    ccode = curl_multi_fdset(curlm, &read_fds, &write_fds, &err_fds, &max_fd);
    max_fd = MAX(max_fd, fifo_fd);

    rc = select(max_fd + 1, &read_fds, &write_fds, &err_fds, &timeout);
    switch (rc)
    {
        case -1:
            WARN("select");
            continue;

        case 0:
        default:
            {
                if (FD_ISSET(fifo_fd, &read_fds))
                {
                    // read from the fifo_fd
                }

                /* Now look at the handles that need attention */
                int old_running_handles = running_handles;

                ccode = curl_multi_perform(curlm, &running_handles);
                if (ccode != CURLM_OK && ccode != CURLM_CALL_MULTI_PERFORM)
                {
                    WARN("curl_multi_perform error: %s", curl_multi_strerror(ccode));
                    continue;
                }

                if (running_handles != old_running_handles)
                {
                    CURLMsg *curl_msg;
                    int left_msgs = 0;
                    while ((curl_msg = curl_multi_info_read(curlm, &left_msgs)) != NULL)
                    {
                        // treat each easy handle
                    }
                }
            }
            break;
    }
}


Q2.在"man 7 fifo"中说:一个进程可以在非阻塞模式下打开FIFO.在这种情况下,即使在写侧尚未打开任何人,只读打开也会成功,而只写打开将失败.除非已打开另一端,否则使用ENXIO(没有此类设备或地址)."但是,即使未打开读取端,进程A始终可以在非阻塞模式下成功打开管道的写入端.这是为什么?我测试的平台是Ubuntu服务器12.04.3,内核3.8.0-29.


Q2. In "man 7 fifo" is said "A process can open a FIFO in nonblocking mode. In this case, opening for read-only will succeed even if no-one has opened on the write side yet, opening for write-only will fail with ENXIO (no such device or address) unless the other end has already been opened." but the process A always can open successfully the write end of the pipe in non-blocking mode even the read end is not opened. Why is that? The platform on which I test is Ubuntu server 12.04.3, kernel 3.8.0-29.

推荐答案

Q1是select()poll()所期望的.请参阅链接的问题.一个合适的解决方案是在同一fifo上打开另一个fd,然后关闭原来的fd.

The Q1 is expected by select() or poll(). See the linked question. A graceful resolution is to open another fd on the same fifo and close the original.

我相信Q2也有望在某些版本的内核上使用. man 7 fifo 包含以下内容:

I believe the Q2 was also expected on some versions of kernel. The man 7 fifo have a paragraph about it:

   Under Linux, opening a FIFO for read and write will succeed both in 
   blocking and nonblocking mode.  POSIX leaves this behavior undefined.
   This can be used to open a FIFO for writing while there are no
   readers available.

该段落似乎声称您可以随时成功打开fifo的写入端,正如原始作者在第二季度所观察到的那样.

That paragraph seems to claim that you can successfully open the write end of a fifo anytime, as observed in Q2 by the original author.

尽管它似乎与前一段矛盾,因为原始问题也在

Though it seems to contradict the previous paragraph as the original question quoted also from the man 7 fifo page that is basically saying the open shall fail instead of succeed:

   A process can open a FIFO in nonblocking mode.  In this case, opening
   for read-only succeeds even if no one has opened on the write side
   yet and opening for write-only fails with ENXIO (no such device or
   address) unless the other end has already been opened.

我看到在4.9.37内核上,当读端未打开时,以非阻塞模式打开写端将失败.我猜它一定已经从3.8版本更改为4.9版本.

I'm seeing opening the write end in non-blocking mode shall fail when the read end is not open, on a 4.9.37 kernel. It must have changed from version 3.8 to 4.9, I guess.

这篇关于在select的非阻塞模式下使用fifo open的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆