* nix select и exceptfds/errorfds семантика

select syscall принимает 3 набора filedescriptor для просмотра fds для чтения/записи и "исключений" на filedescriptor.

Мой выбор man-страница не содержит много информации о наборе дескрипторов exceptfd. Для чего его используют; какие исключения могут и будут ли они уведомлять о дескрипторах файлов?

Я предполагаю, что это может быть разным для типа дескриптора... будь то TCP-сокет, труба, tty и т.д.). У кого-нибудь есть дополнительная информация о том, какие ошибки select могут сообщать о разных типах дескрипторов?

Ответ 1

Иногда считается, что exceptfds необходимо для обнаружения ошибок, но это неправильное представление. Ошибки будут отмечены в readfds. Хотя POSIX требует (и даже вызывает параметр errorfds), это зависит от ОС, независимо от того, отмечены ли ошибки в exceptfds. Действительно, этот параметр необходим только в том случае, если вы заботитесь об исключительных условиях, но редко приходится обнаруживать их.

То, что квалифицируется как исключительное условие, зависит от типа файлового дескриптора, но, безусловно, наиболее распространенное использование имеет место в сокете TCP, где указано, что данные вне полосы доступны для чтения с помощью recv() с MSG_OOB. Однако у внеполосных данных TCP есть несколько причуд (например, только один байт может быть выдающимся) и в результате редко используется.

В последних ядрах Linux exceptfds можно использовать для обнаружения изменений некоторых атрибутов sysfs. Текущее значение атрибута можно прочитать, прочитав соответствующий файл в /sys, а select() в файловом дескрипторе будет отмечать exceptfds при изменении атрибута. Однако в настоящее время это работает только для некоторых атрибутов и для изменений монтирования (/proc/mounts).

Также некоторые драйверы устройств будут отмечать определенные условия для конкретного устройства, используя exceptfds.

Ответ 2

Вы правы, это зависит от типа устройства, на которое вы ссылаетесь на файловые дескрипторы. Таким образом, он отличается для сокетов, FIFO, последовательных портов и т.д.

Посмотрите справочную страницу для чтения(). Внизу (по крайней мере, в OS X) перечислены различные ошибки, которые вы можете получить для разных устройств. То же самое касается write().

Для сокетов, FIFO и других механизмов IPC я бы рассмотрел Unix Network Programming, тома 1 и 2. IIRC описывает, какие ошибки можно ожидать для разных условий ошибки.

Я прошел этот путь один раз с FIFO. Я закончил мозговой штурм всех способов, которыми производитель и потребитель мог взаимодействовать с каждым концом FIFO, а затем написал тестовые примеры для каждой из этих ситуаций. Это был хороший (хотя и утомительный) способ обнаружить все различные условия ошибки. Я многому научился, и, в конечном счете, код сейчас работает.