8

A と B の 2 つのプロセスがあります。通信フローは常に A -> B ですが、名前付きパイプを使用して行う必要があります。これは、B プロセス内の選択呼び出しでパイプ ファイル記述子を使用し、データを書き込む必要があるためです。プロセスのいずれかまたは両方が終了しても、パイプへの接続は持続する必要があります。

パイプは両端でノンブロッキング モードで開かれます。プロセス 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 を呼び出して、読み取りと書き込みに使用できるファイル記述子を取得します。select の呼び出しごとに、結果の read fd_set に "fd" が含まれますが、read は、write エンドがオープンされていても 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;
    }
}

Q2. 「man 7 fifo」では、「プロセスは FIFO をノンブロッキング モードで開くことができます。この場合、書き込み側でまだ誰も開いていなくても読み取り専用で開くと成功し、書き込み専用で開くと失敗します」と書かれています。もう一方の端がすでに開かれていない限り、ENXIO (そのようなデバイスまたはアドレスはありません) を使用します。」ただし、プロセス A は、読み取り側が開かれていない場合でも、パイプの書き込み側をノンブロッキング モードで常に正常に開くことができます。何故ですか?私がテストするプラットフォームは、Ubuntu サーバー 12.04.3、カーネル 3.8.0-29 です。

4

2 に答える 2