2016-12-02 15 views
4

Согласно man ioctl, открывающие дескрипторы файлов с open могут вызывать нежелательные побочные эффекты. В руководстве также говорится, что открытие с O_NONBLOCK решает эти нежелательные проблемы, но я не могу найти причину этого и каковы фактические побочные эффекты. Может ли кто-то пролить свет на это? С ioctl всегда возможно и равнозначно * открывать дескрипторы файлов с помощью O_NONBLOCK?Каковы нежелательные побочные эффекты открытого в ioctl?

ПРИМЕЧАНИЯ (от man ioctl)

Для того, чтобы использовать этот вызов, один нужен открытый дескриптор файла. Часто открытый (2) вызов имеет нежелательные побочные эффекты, которых можно избежать под Linux, предоставив ему флаг O_NONBLOCK.

(* Я знаю, что O_NONBLOCK подразумевает, но я не знаю, если это влияет на ioctl вызовы так же, как она влияет на другие системные вызовы. Моя программа, которая использует ioctl для записи и чтения с шины SPI, отлично работает с этим флагом включен)

+0

Поскольку ioctls являются средними для доступа к специфичным для устройства функциям, невозможно сказать, не зная, о чем вы говорите. Btw. это похоже на 'opne'. – Olaf

+2

Последовательные порты, вероятно, являются основной проблемной областью. Традиционно открытие устройства tty посылает сигнал, который обнаруживается устройством на другом конце последовательного кабеля. См. [Этот вопрос] (http://stackoverflow.com/q/5090451/2404501) для примера обсуждения (в котором не было вывода, что 'O_NONBLOCK' предотвратит его, но нет возможности предотвратить его!) –

+0

Другая идея, которая просто пришла на ум, - это съемное хранилище. Если вы хотите открыть '/ dev/cdrom' для вызова извлечения ioctl, вам может потребоваться указать' O_NONBLOCK', чтобы он не пытался прочитать диск? И/или что-то подобное для лент и дискет? Это непроверенные догадки, хотя ... –

ответ

4

очевидное место, чтобы искать ответ будет страница open(2) человек, который под заголовком для O_NONBLOCK, говорит:.

Когда это возможно, файл открывается в неблокирующем режиме. Ни функция open(), ни последующие операции над возвращаемым дескриптором файла не приведут к вызову .

[...]

Для обработки FIFOs (именованные каналы), см также fifo(7). Для обсуждения эффекта O_NONBLOCK в сочетании с с обязательными блокировками файлов и файлами, см. fcntl(2).

ОК, это было не очень информативно, но давайте следовать по ссылкам и посмотреть, что страницы руководства для ФИФО (7) и Fcntl (2) говорят:

Обычно, открытие блоки FIFO пока не откроется другой конец.

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

Под Linux открытие FIFO для чтения и записи будет успешным как в режиме блокировки и неблокирования . POSIX оставляет это поведение неопределенным.

Так вот, по крайней мере один «нежелательный побочный эффект»: даже просто пытается открыть FIFO может блокировать, если вы не пройдете O_NONBLOCK к open() вызова (и открыть его для чтения).

А как насчет fcntl? Как видно из справочной страницы open (2), разделы, на которые нужно смотреть, - это заголовок «Обязательная блокировка» и «Файловая аренда».Это кажется мне, что обязательные замки, в данном случае, являются отвлекающим маневром, хотя — они только причиной блокировки, когда один пытается на самом деле для чтения или записи в файл:

Если процесс пытается выполнить несовместимый доступ (например, чтение (2) или запись (2)) в области файлов, которая имеет несовместимую обязательную блокировку , тогда результат зависит от того, включен ли флаг O_NONBLOCK 10 для его открытого описания файла. Если флаг O_NONBLOCK не активирован, системный вызов блокируется до , блокировка удаляется или преобразуется в режим, совместимый с доступом.

Как насчет аренды?

Когда процесс («аренда выключатель») выполняет открытые (2) или TRUNCATE (2), который конфликтует с арендой, установленной с помощью F_SETLEASE, системного вызова блокируются ядром и извещают ядра арендодателя , отправив ему сигнал (по умолчанию SIGIO). [...]

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

[...] Если аренды выключатель определяет флаг O_NONBLOCK при вызове открытым (2), тогда вызов немедленно завершается с EWOULDBLOCK ошибки, но другие шаги, все еще имеют место, как описано выше.

ОК, так что это еще нежелательный побочный эффект: если файл, который вы пытаетесь открыть имеет аренду на нем, то open() вызов может блокироваться, пока держатель аренды не выпустил аренды.

В обоих случаях «нежелательного побочного эффекта» избегали пропусканием O_NONBLOCK к open(), что не удивительно, сам open() блокировки вызовов, пока другой процесс не сделал что-то. Если есть любые другие виды побочных эффектов, на которые ссылается страница, на которую ссылается человек, я не знаю о них.

1

С системного программирования Linux, 2-е издание, Р. Любовь (курсив мой):

O_NONBLOCK Если возможно, файл будет открыт в неблокируемом режиме. Ни вызов open(), , ни любая другая операция не приведет к блокировке (спящему) процессу ввода-вывода. Это поведение может быть определено только для FIFO.

Иногда программисты не хотят, чтобы запрос на чтение() блокировался, когда есть данных нет . Вместо этого они предпочитают, чтобы звонок немедленно возвращался, , указывающий, что нет данных .Это называется неблокирующим вводом-выводом; он позволяет приложениям выполнять операции ввода-вывода, потенциально на нескольких файлах, без блокировки, и, следовательно, отсутствующие данные доступны в другом файле.

Следовательно, дополнительное значение errno стоит проверить: EAGAIN.

См. this thread в списке рассылки ядра.