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:
POLLIN
stane se, když je vstup dostupnýPOLLHUP
nastane, když je soubor uzavřen pomocíprintf
close(pfd.fd);
apfd.fd *= -1;
vyčistit věci a přestaneme dostávatPOLLHUP
poll
visí 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:
POLLIN
aPOLLHUP
aclose
stalo jako předtím- protože jsme nenastavili
pfd.fd
na záporné číslo,poll
stále zkouší používatfd
že jsme zavřeli - toto stále vrací
POLLNVAL
navž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.