使用fifo以非阻塞模式打开并选择

Vic*_*don 5 c linux curl fifo

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

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

int push_fifo_fd = open(FIFO_NAME, O_WRONLY | O_NONBLOCK | O_CREAT, 0644);
Run Code Online (Sandbox Code Playgroud)

在流程B中:

int fd = open(FIFO_NAME, O_RDONLY | O_NONBLOCK | O_CREAT, 0644);
Run Code Online (Sandbox Code Playgroud)

Q1.进程B使用curl多接口,因此我得到curl多句柄的fd_sets并将"fd"描述符添加到读取fd_set,而不是调用select,以获得可用于读取和写入的文件描述符.在每次调用调用中,"fd"包含在结果读取fd_set中,但是读取返回0,即使写入结束也是如此.这导致进程B使用100%的处理器时间.我提到我不知道订购哪个管子的末端是打开的.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

小智 0

因为:

在 Linux 下,打开 FIFO 进行读写在阻塞和非阻塞模式下都会成功。POSIX 未定义此行为。这可用于在没有可用读取器时打开 FIFO 进行写入。使用连接两端以便与自身通信的进程应该非常小心,以避免死锁。

来自http://linux.die.net/man/7/fifo