Mit fifo-open-im nicht-blockierenden Modus mit wählen Sie

Habe ich zwei Prozesse A und B. Die flow-Kommunikation ist immer Ein -> B, aber ich muss es tun mit Hilfe einer named pipe, da muss ich das pipe-file-descriptor in einer select-Aufruf in der B-Prozess, und die geschriebenen Daten in die pipe muss bestehen, wenn einzelne oder beide Prozesse beenden.

Das Rohr ist geöffnet im nicht-blockierenden Modus an beiden enden. In den Prozess Ein:

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

In Prozess B:

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

Q1.
Das Verfahren B verwendet die curl-multi-interface, so bekomme ich die fd_sets der curl-multi-handle und fügen Sie die "fd" - Deskriptor zum Lesen fd_set, als einen Anruf zu wählen, um die Datei-Deskriptoren verfügbar für lese-und Schreibvorgänge. Bei jedem Aufruf wählen, "fd" enthalten ist, in das Ergebnis zu Lesen fd_set, aber Lesen liefert 0, sogar wenn der Schreibvorgang zu Ende ist geöffnet. Dies bewirkt, dass der Prozess B zu 100% der Prozessor-Zeit. Ich erwähnen, dass ich nicht weiß, in welcher Reihenfolge Sie die enden des Rohres sind geöffnet. Der entsprechende code aus 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. In "man 7 fifo" wird gesagt, "Einen Prozess öffnet ein FIFO in nonblocking-Modus. In diesem Fall, der öffnung für den nur-lese-gelingen wird, auch wenn niemand geöffnet hat, auf der schreiben-Seite noch eine öffnung für den nur-schreiben-fehl mit ENXIO (kein solches Gerät oder Adresse), es sei denn, das andere Ende ist bereits geöffnet.", aber der Prozess, Ein immer öffnen kann erfolgreich die write-Ende der pipe im non-blocking-Modus auch das lese-Ende ist nicht geöffnet. Warum ist das so? Die Plattform, auf der ich Teste ist Ubuntu server 12.04.3, kernel 3.8.0-29.

  • Falls es wichtig ist, dass die Datei bezeichnet, die von FIFO_NAME in der Tat ein FIFO ist, dann ist es kontraproduktiv, zu verwenden O_CREAT wenn Sie es öffnen, entweder schreiben oder Lesen. Wenn open() überhaupt nicht haben, um es zu schaffen dann wird es so tun, wie eine gewöhnliche Datei.
  • Das beschriebene Verhalten in dieser Frage scheint dem zu widersprechen, die Dokumentation der relevanten Systemschnittstellen. Normalerweise, ich würde die OP eine chance geben, um eine MCVE, aber angesichts der Tatsache, dass es ein fünf-Jahr-alten necro würde Fragen, es scheint unwahrscheinlich, dass ein MCVE werden in Kürze. Geradeaus, um die Abstimmung zu schließen, statt.
  • Ich sehe die Q1 problem auf kernel-4.9.37, aber nicht die Q2 problem.
  • Sie muss den Fall behandeln, in denen select() gibt null zurück, getrennt. und nicht überprüfen die FD_SETs in diesem Fall.
  • Angenommen separaten reader-und writer-Prozesse öffnen ein FIFO. Auf den meisten Systemen, wenn der Autor schreibt, um die FIFO-und Ausfahrten, und der reader wird ebenfalls beendet, ohne dass die Lektüre der SCHRIFTLICHEN Informationen, die ungelesen Informationen werden verworfen, wenn der Letzte Prozess, mit einem offenen file-Deskriptor für die FIFO-geschlossen (z.B. weil er sich beendet). Somit ist die Verwendung einer FIFO-nicht die Anforderung "werden die Daten geschrieben, um die Leitung muss bestehen, wenn einzelne oder beide Prozesse beenden" auf den meisten Systemen. [...Fortsetzung...]
  • [...Fortsetzung...] . Demo: mkfifo FIFO; (echo "Hello World" > FIFO) & (echo "Hi" < FIFO); (echo "Goodbye, Cruel World!" > FIFO) & cat FIFO; rm -f FIFO — Der Ausgang ist Hi und Goodbye, Cruel World! (plus job-control-Informationen). Die Informationen Hello World! verloren. Ändern echo "Hi" < FIFO zu cat FIFO und die Hello World! gesehen wird (und kein "Hallo", denn das ist irgendwo nicht geschrieben).

InformationsquelleAutor Victor Dodon | 2013-10-25
Schreibe einen Kommentar