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 verwendenO_CREAT
wenn Sie es öffnen, entweder schreiben oder Lesen. Wennopen()
ü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 istHi
undGoodbye, Cruel World!
(plus job-control-Informationen). Die InformationenHello World!
verloren. Ändernecho "Hi" < FIFO
zucat FIFO
und dieHello World!
gesehen wird (und kein "Hallo", denn das ist irgendwo nicht geschrieben).
Du musst angemeldet sein, um einen Kommentar abzugeben.
Q1 erwartet
select()
oderpoll()
. Finden Sie die verknüpfte Frage. Eine anmutige Lösung ist, um zu öffnen, eine andere fd, die auf den gleichen fifo-und schließe das original.Ich glaube das Q2 wurde auch erwartet, dass in einigen Versionen von kernel. Die Mann 7 fifo ein Absatz darüber:
Absatz scheint zu behaupten, dass Sie erfolgreich können öffnen Sie die schreiben das Ende einer fifo-jederzeit, wie bereits im Q2 durch den ursprünglichen Autor.
Obwohl es anscheinend im Widerspruch zum vorherigen Absatz, wie die ursprüngliche Frage zitierte auch aus der Mann 7 fifo Seite, die im Grunde sagen, das geöffnet wird scheitern, statt erfolgreich:
Sehe ich das öffnen des schreib-Ende im nicht-blockierenden Modus wird fehlschlagen, wenn das lese-Ende ist nicht offen, auf eine 4.9.37 kernel. Es muss geändert von version 3.8 auf 4.9, denke ich.
Weil:
vom http://linux.die.net/man/7/fifo