POLLNVAL
bedeutet, dass der Dateideskriptorwert ungültig ist. Normalerweise weist es auf einen Fehler in Ihrem Programm hin, aber Sie können sich auf poll
verlassen Rückgabe von POLLNVAL
wenn Sie einen Dateideskriptor geschlossen und seitdem keine Datei mehr geöffnet haben, könnte der Deskriptor wiederverwendet worden sein.
POLLERR
ähnelt den Fehlerereignissen von select
. Es zeigt an, dass ein read
oder write
Aufruf würde eine Fehlerbedingung (z. B. I/O-Fehler) zurückgeben. Dies schließt keine Out-of-Band-Daten ein, die select
sind Signale über seinen errorfds
Maske, aber poll
Signale über POLLPRI
.
POLLHUP
bedeutet im Grunde, dass das, was am anderen Ende der Verbindung ist, sein Ende der Verbindung geschlossen hat. POSIX beschreibt es als
Das Gerät wurde getrennt. Dieses Event und POLLOUT schließen sich gegenseitig aus; ein Stream kann niemals beschreibbar sein, wenn ein Hangup aufgetreten ist.
Für ein Terminal ist dies klar genug:Das Terminal ist weg (dasselbe Ereignis, das ein SIGHUP erzeugt:Die Modemsitzung wurde beendet, das Fenster des Terminalemulators wurde geschlossen usw.). POLLHUP
wird nie für eine normale Datei gesendet. Bei Pipes und Sockets hängt es vom Betriebssystem ab. Linux setzt POLLHUP
wenn das Programm am schreibenden Ende einer Pipe die Pipe schließt und POLLIN|POLLHUP
setzt wenn das andere Ende eines Sockets den Socket schloss, aber POLLIN
nur für ein Socket-Shutdown. Neuer *BSD-Satz POLLIN|POLLUP
wenn das schreibende Ende einer Pipe die Pipe schließt, und das Verhalten für Sockets variabler ist.
Ein POLLHUP
bedeutet, dass die Steckdose nicht mehr verbunden ist. In TCP bedeutet dies, dass FIN empfangen und gesendet wurde.
Ein POLLERR
bedeutet, dass der Socket einen asynchronen Fehler erhalten hat. Bei TCP bedeutet dies normalerweise, dass ein RST empfangen oder gesendet wurde. Wenn der Dateideskriptor kein Socket ist, POLLERR
könnte bedeuten, dass das Gerät Polling nicht unterstützt.
Für beide oben genannten Bedingungen ist der Socket-Dateideskriptor noch geöffnet und wurde noch nicht geschlossen (aber shutdown()
wurde vielleicht schon angerufen). Ein close()
im Dateideskriptor gibt Ressourcen frei, die noch für den Socket reserviert sind. Theoretisch sollte es möglich sein, den Socket sofort wiederzuverwenden (z. B. mit einem anderen connect()
anrufen).
Ein POLLNVAL
bedeutet, dass der Socket-Dateideskriptor nicht geöffnet ist. Es wäre ein Fehler zu close()
es.
Es hängt von der genauen Fehlerart ab. Verwenden Sie getsockopt(), um das Problem zu sehen:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Werte:http://www.xinotes.net/notes/note/1793/
Am einfachsten geht man davon aus, dass der Socket ohnehin nicht mehr nutzbar ist und schließt ihn.
Minimales FIFO-Beispiel
Sobald Sie verstehen, wann diese Bedingungen auftreten, sollten Sie leicht wissen, was damit zu tun ist.
poll.c
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
char buf[1024];
int fd, n;
short revents;
struct pollfd pfd;
fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
poll(&pfd, 1, -1);
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP\n");
close(pfd.fd);
pfd.fd *= -1;
}
if (revents & POLLNVAL) {
printf("POLLNVAL\n");
}
if (revents & POLLERR) {
printf("POLLERR\n");
}
}
}
GitHub-Upstream.
Kompilieren mit:
gcc -o poll.out -std=c99 poll.c
Verwendung:
sudo mknod -m 666 poll0.tmp p
./poll.out
Auf einer anderen Shell:
printf a >poll0.tmp
UMFRAGE
Wenn Sie die Quelle nicht ändern:./poll.out
Ausgaben:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
Also:
POLLIN
geschieht, wenn Eingaben verfügbar werdenPOLLHUP
passiert, wenn die Datei durchprintf
geschlossen wirdclose(pfd.fd);
undpfd.fd *= -1;
aufräumen und wir hören aufPOLLHUP
zu empfangenpoll
hängt für immer
Dies ist der normale Vorgang.
Sie könnten jetzt den FIFO erneut anweisen, auf den nächsten open
zu warten , oder beenden Sie die Schleife, wenn Sie fertig sind.
POLLNAL
Wenn Sie pfd.fd *= -1;
auskommentieren :./poll.out
druckt:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
und Endlosschleifen.
Also:
POLLIN
undPOLLHUP
undclose
geschah wie zuvor- da wir
pfd.fd
nicht gesetzt haben zu einer negativen Zahl,poll
versucht weiterhin, denfd
zu verwenden dass wir geschlossen haben - dies gibt ständig
POLLNVAL
zurück für immer
Wir sehen also, dass dies nicht hätte passieren dürfen, und weist auf einen Fehler in Ihrem Code hin.
POLLER
Ich weiß nicht, wie ich einen POLLERR
generieren soll mit FIFOs. Lassen Sie mich wissen, ob es einen Weg gibt. Mit file_operations
sollte es aber möglich sein eines Gerätetreibers.
Getestet in Ubuntu 14.04.