POLLNVAL znamená, že hodnota deskriptoru souboru je neplatná. Obvykle to znamená chybu ve vašem programu, ale můžete se spolehnout na poll vrací POLLNVAL pokud jste zavřeli deskriptor souboru a od té doby jste žádný soubor neotevřeli, mohlo dojít k opětovnému použití deskriptoru.
POLLERR je podobný chybovým událostem z select . Znamená to read nebo write volání by vrátilo chybový stav (např. I/O chyba). To nezahrnuje data mimo pásmo, která select signály přes jeho errorfds maska, ale poll signály přes POLLPRI .
POLLHUP v podstatě znamená, že to, co je na druhém konci spojení, uzavřelo svůj konec spojení. POSIX to popisuje jako
Zařízení bylo odpojeno. Tato událost a POLLOUT se vzájemně vylučují; do streamu nelze nikdy zapisovat, pokud došlo k zablokování.
To je pro terminál dostatečně jasné:terminál odešel (stejná událost, která generuje SIGHUP:relace modemu byla ukončena, okno emulátoru terminálu bylo zavřeno atd.). POLLHUP není nikdy odesláno pro běžný soubor. U trubek a zásuvek záleží na operačním systému. Linux nastaví POLLHUP když program na zapisovacím konci roury zavře roura a nastaví POLLIN|POLLHUP když druhý konec soketu uzavřel soket, ale POLLIN pouze pro vypnutí zásuvky. Nedávné *BSD sada POLLIN|POLLUP když zapisovací konec roury rouru uzavírá a chování soketů je variabilnější.
A POLLHUP znamená, že zásuvka již není připojena. V TCP to znamená, že FIN byl přijat a odeslán.
A POLLERR znamená, že soket dostal asynchronní chybu. V TCP to obvykle znamená, že byl přijat nebo odeslán RST. Pokud deskriptor souboru není soket, POLLERR může znamenat, že zařízení nepodporuje dotazování.
Pro obě výše uvedené podmínky je deskriptor souboru soketu stále otevřený a ještě nebyl uzavřen (ale shutdown() možná již byl volán). A close() na deskriptoru souboru uvolní prostředky, které jsou stále rezervovány jménem soketu. Teoreticky by mělo být možné okamžitě znovu použít soket (např. s jiným connect() zavolat).
A POLLNVAL znamená, že deskriptor souboru soketu není otevřený. Byla by chyba close() to.
Záleží na přesné povaze chyby. Použijte getockopt() k zobrazení problému:
int error = 0;
socklen_t errlen = sizeof(error);
getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
Hodnoty:http://www.xinotes.net/notes/note/1793/
Nejjednodušší způsob je předpokládat, že socket již není v žádném případě použitelný a zavřít jej.
Minimální příklad FIFO
Jakmile pochopíte, kdy tyto podmínky nastanou, mělo by být snadné vědět, co s nimi dělat.
anketa.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.
Kompilace s:
gcc -o poll.out -std=c99 poll.c
Použití:
sudo mknod -m 666 poll0.tmp p
./poll.out
Na jiném shellu:
printf a >poll0.tmp
POLLHUP
Pokud zdroj neupravíte:./poll.out výstupy:
loop
POLLIN n=1 buf=a
loop
POLLHUP
loop
Takže:
POLLINstane se, když je vstup dostupnýPOLLHUPnastane, když je soubor uzavřen pomocíprintfclose(pfd.fd);apfd.fd *= -1;vyčistit věci a přestaneme dostávatPOLLHUPpollvisí navždy
Toto je normální operace.
Nyní můžete odvolat FIFO, aby počkal na další open , nebo ukončete smyčku, pokud jste hotovi.
POLLNAL
Pokud zakomentujete pfd.fd *= -1; :./poll.out tisky:
POLLIN n=1 buf=a
loop
POLLHUP
loop
POLLNVAL
loop
POLLNVAL
...
a smyčky navždy.
Takže:
POLLINaPOLLHUPaclosestalo jako předtím- protože jsme nenastavili
pfd.fdna záporné číslo,pollstále zkouší používatfdže jsme zavřeli - toto stále vrací
POLLNVALnavždy
Vidíme tedy, že se to stát nemělo, a ukazuje to na chybu ve vašem kódu.
POLLERR
Nevím, jak vygenerovat POLLERR s FIFO. Dejte mi vědět, jestli existuje způsob. Ale mělo by to být možné s file_operations ovladače zařízení.
Testováno v Ubuntu 14.04.