POLLHUP против POLLNVAL, или что такое POLLHUP?
Руководства говорят для опроса (2):
POLLHUP - повесить трубку (только вывод)
POLLNVAL - Неверный запрос: fd не открыт (только вывод)
В чем именно разница? Написание простой программы показывает, что POLLNVAL
сработает, если я закрою дескриптор файла, затем попробую прочитать с закрытого fd. Тем не менее, я не могу найти способ вернуть POLLHUP
,
3 ответа
POLLNVAL
эквивалентно EBADF
: это означает, что дескриптор файла на самом деле не ссылается ни на один открытый файл, т.е. close
г или никогда не открывать для начала. Это никогда не может произойти, кроме как в результате ошибки программирования или преднамеренной попытки запросить, является ли дескриптор файла недействительным. Внешние условия, такие как одноранговый узел, закрывающий свой конец сетевого сокета или канала, никогда не могут закрыть ваш файловый дескриптор до вашего конца сокета или канала. Если бы это было возможно, это привело бы к огромным уязвимостям практически любой программы, использующей сокеты / каналы / и т.д.
POLLHUP
с другой стороны, указывает, что ваш дескриптор файла действителен, но находится в состоянии, где:
Устройство было отключено или канал или FIFO были закрыты последним процессом, открывшим его для записи. После установки состояние зависания FIFO должно сохраняться до тех пор, пока какой-либо процесс не откроет FIFO для записи или пока не будут закрыты все файловые дескрипторы только для чтения для FIFO. Это событие и ПРОДАЖА являются взаимоисключающими; поток никогда не может быть доступен для записи, если произошло зависание. Однако это событие и POLLIN, POLLRDNORM, POLLRDBAND или POLLPRI не являются взаимоисключающими. Этот флаг действителен только в битовой маске это должно быть проигнорировано в участнике событий.
Источник: http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
Если вы хотите увидеть POLLHUP
Просто откройте pipe
закройте конец чтения и запросите конец записи с помощью poll
,
Если ваша цель - написать программу, которая запускает POLLHUP
попробуйте что-то вроде открытия канала, закрытия конца записи и затем poll()
конец чтения (код изменен с http://www.greenend.org.uk/rjk/tech/poll.html):
#include <unistd.h>
#include <stdio.h>
#include <poll.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main(void)
{
int p[2];
struct pollfd ufd;
if (pipe(p) < 0) {
perror("pipe");
return EXIT_FAILURE;
}
if (close(p[1]) < 0) { /* close the write fd */
perror("close");
return EXIT_FAILURE;
}
memset(&ufd, 0, sizeof ufd);
ufd.fd = p[0]; /* poll the read fd after the write fd is closed */
ufd.events = POLLIN;
if (poll(&ufd, 1, 1000) < 0) {
perror("poll");
return EXIT_FAILURE;
}
switch(ufd.revents & (POLLIN|POLLHUP)) {
case POLLIN: printf("POLLIN\n"); break;
case POLLHUP: printf("POLLHUP\n"); break;
case POLLIN|POLLHUP: printf("POLLIN|POLLHUP\n"); break;
case POLLERR: printf("POLLERR\n"); break;
default: printf("%#x\n", (unsigned)ufd.revents); break;
}
return EXIT_SUCCESS;
}
Вышеуказанные принты POLLHUP
для меня.
POLLNVAL
означает, что значение дескриптора файла недопустимо. Обычно это указывает на ошибку в вашей программе, но вы можете положиться на poll
возврате POLLNVAL
если вы закрыли файловый дескриптор и с тех пор не открыли ни одного файла, возможно, этот дескриптор использовался повторно.
POLLHUP
в основном означает, что то, что находится на другом конце соединения, закрыло свой конец соединения. POSIX описывает это как
Устройство было отключено. Это событие и ПРОДАЖА являются взаимоисключающими; поток никогда не может быть доступен для записи, если произошло зависание.
Это достаточно ясно для терминала: терминал ушел (то же самое событие, которое генерирует SIGHUP: сеанс модема был завершен, окно эмулятора терминала было закрыто и т. Д.). POLLHUP
никогда не отправляется для обычного файла. Для труб и розеток это зависит. Наборы Linux POLLHUP
когда программа на конце записи канала закрывает канал и устанавливает POLLIN|POLLHUP
когда другой конец сокета закрыл сокет, но POLLIN
только для отключения розетки. Недавний *BSD набор POLLIN|POLLUP
когда записывающий конец канала закрывает канал, и поведение для сокетов более изменчиво.
Наблюдать POLLHUP
, прочитайте вашу программу из терминала и закройте терминал. Или, в Linux, ваша программа читает из канала и закрывает конец записи (например, sleep 1 | yourprogram
).