UNIX, не блокирующий ввод-вывод: O_NONBLOCK по сравнению с FIONBIO

"все" и "любой" хороши для многих условий того же случая типа. НО они всегда оценивают все условия. Как показано в этом примере:

def c1():
    print " Executed c1"
    return False
def c2():
    print " Executed c2"
    return False


print "simple and (aborts early!)"
if c1() and c2():
    pass

print

print "all (executes all :( )"
if all((c1(),c2())):
    pass

print
90
задан HostileFork 1 February 2017 в 03:42
поделиться

3 ответа

До стандартизации существовали ioctl ( ... FIONBIO ... ) и fcntl ( ... O_NDELAY ... ) , но они вели себя непоследовательно между системами и даже внутри одной системы. Например, FIONBIO было обычным делом для работы с сокетами, а O_NDELAY для работы с ttys, с большой несогласованностью для таких вещей, как каналы, FIFO и устройства. И если вы не знаете, какой у вас файловый дескриптор, вам придется установить оба, чтобы быть уверенным. Но кроме того, неблокирующее чтение при отсутствии данных также указывалось непоследовательно; в зависимости от ОС и типа файлового дескриптора при чтении может возвращаться 0 или -1 с ошибкой EAGAIN или -1 с ошибкой EWOULDBLOCK. Даже сегодня, установка FIONBIO или O_NDELAY в Solaris приводит к тому, что чтение без данных возвращает 0 на tty или конвейере или -1 с ошибкой EAGAIN на сокете. Однако значение 0 является неоднозначным, поскольку оно также возвращается для EOF.

POSIX решил эту проблему с введением O_NONBLOCK , который имеет стандартизованное поведение для различных систем и типов файловых дескрипторов. Поскольку существующие системы обычно хотят избежать каких-либо изменений в поведении, которые могут нарушить обратную совместимость, POSIX определил новый флаг, а не предписывал конкретное поведение для одного из других. Некоторые системы, такие как Linux, обрабатывают все 3 одинаково, а также определяют EAGAIN и EWOULDBLOCK с одним и тем же значением, но системы, желающие сохранить какое-либо другое устаревшее поведение для обратной совместимости, могут сделать это при использовании старых механизмов.

129
ответ дан 24 November 2019 в 07:05
поделиться

Как сказал @Sean, fcntl () в значительной степени стандартизирован и поэтому доступен на всех платформах. Функция ioctl () предшествовала fcntl () в Unix, но совсем не стандартизирована. То, что ioctl () работал для вас на всех релевантных для вас платформах, это удача, но не гарантируется. В частности, имена, используемые для второго аргумента, непонятны и ненадежны для разных платформ. Действительно, они часто уникальны для конкретного драйвера устройства, на который ссылается файловый дескриптор. (Вызовы ioctl () , используемые для устройства с побитовой графикой, работающего на ICL Perq под управлением PNX (Perq Unix) двадцатилетней давности, никогда не переводились, например, ни на что другое).

5
ответ дан 24 November 2019 в 07:05
поделиться

Я считаю, что fcntl () - это функция POSIX. Где ioctl () - это стандартная вещь UNIX. Вот список POSIX io . ioctl () очень специфичен для ядра / драйвера / ОС, но я уверен, что то, что вы используете, работает в большинстве разновидностей Unix. некоторые другие ioctl () вещи могут работать только на определенных ОС или даже на определенных версиях ядра.

6
ответ дан 24 November 2019 в 07:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: