Подтвердить что ты не робот

Конец неблокирующего файла

Как обнаружен конец файла для файла в неблокирующем режиме?

4b9b3361

Ответ 1

По крайней мере, на POSIX (включая Linux) очевидным ответом является то, что неблокирующие обычные файлы не существуют. Регулярные файлы ВСЕГДА блокируются, а O_NONBLOCK игнорируется.

Аналогично, poll()/select() et al. всегда укажет вам, что fd, указывающий на обычный файл, готов к вводу/выводу, независимо от того, готовы ли данные в кеше страницы или все еще на диске (в основном для чтения).

EDIT И, поскольку O_NONBLOCK - нет-op для обычных файлов, read() в обычном файле никогда не будет устанавливать errno в EAGAIN, вопреки тому, что утверждает другой ответ на этот вопрос.

Ссылки EDIT2:

Из спецификации POSIX (p) select(): "Дескрипторы файлов, связанные с обычными файлами, всегда должны быть выбраны для чтения, готовые к записи и условия ошибки."

Из спецификации POSIX poll(): "Обычные файлы должны всегда регистрировать TRUE для чтения и записи".

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

Помимо вышеизложенного, есть, по крайней мере, некоторые косвенные доказательства.

Из спецификации POSIX open(): определяется поведение файловых дескрипторов, ссылающихся на каналы, блокировать специальные файлы и специальные файлы символов, "В противном случае поведение O_NONBLOCK не указано".

Некоторые связанные ссылки:

http://tinyclouds.org/iocp-links.html

http://www.remlab.net/op/nonblock.shtml

http://davmac.org/davpage/linux/async-io.html

И даже здесь, в stackoverflow:

Может ли обычное чтение файлов извлекаться из неблокирующего-IO?

Как указывает ответ Р., из-за того, как работает кеширование страниц, не-блокирование для обычных файлов не очень легко определить. Например. что если какой-то механизм вы обнаружите, что данные готовы к чтению в кеше страниц, а затем, прежде чем вы его прочтете, ядро ​​решит выбить эту страницу из кэша из-за давления памяти? Он отличается от таких вещей, как сокеты и каналы, потому что правильность требует, чтобы данные не отбрасывались именно так.

Также, как бы вы выбрали /poll для файлового дескриптора поиска? Вам понадобится какой-то новый API, который поддерживает определение диапазона байтов в интересующем вас файле. И реализация ядра этого API будет привязана к системе VM, так как это должно было бы предотвратить страницы, которые вам интересны от выбивания. Это означало бы, что эти страницы будут считаться с лимитом заблокированных страниц процесса (см. Ulimit -l), чтобы предотвратить DOS. И когда эти страницы будут разблокированы? И так далее.

Ответ 2

Это действительно хороший вопрос. Неблокирующие сокеты возвращают пустую строку из recv(), а не бросают socket.error, указывая на отсутствие данных. Для файлов, однако, похоже, нет прямого индикатора, доступного для Python.

Единственным механизмом, который я могу придумать для обнаружения EOF, является сравнение текущей позиции файла с общим размером файла после получения пустой строки:

def read_nonblock( fd ):
    t = os.read(fd, 4096)
    if t == '':
        if os.fstat(fd).st_size == os.lseek(fd, 0, os.SEEK_CUR):
            raise Exception("EOF reached")
    return t

Это, конечно, предполагает, что обычные файлы в неблокирующем режиме будут фактически возвращаться немедленно, а не ждать, пока данные будут считаны с диска. Я не уверен, что это правда в Windows или Linux. Было бы неплохо проверить, но я не удивлюсь, если чтение обычных файлов даже в неблокирующем режиме возвращает пустую строку, когда встречается фактический EOF.

Ответ 3

Хороший трюк, который хорошо работает в С++ (YMMV), заключается в том, что если количество возвращаемых данных меньше, чем размер буфера (т.е. буфер не заполнен), вы можете смело предположить, что транзакция завершена. тогда есть вероятность 1/buffersize, что последняя часть файла полностью заполняет буфер, поэтому для большого размера буфера вы можете быть уверены, что транзакция закончится незаполненным буфером, и, если вы проверите количество данных возвращаются к размеру буфера, и они не равны, вы знаете, что произошла ошибка или транзакция завершена. Не уверен, что это переведёт на python, но это мой метод определения EOF

Ответ 4

Не выбираете, скажите, что есть что читать, даже если это только EOF? Если он говорит вам, что есть что-то читать, и вы ничего не получаете, тогда это должен быть EOF. Я считаю, что это относится к сокетам.

Ответ 5

Для файлов установка дескриптора файла как неблокирующего ничего не делает - все IO все равно блокируются.

Если вам действительно нужен неблокирующий файл IO, вам нужно обратиться к aio_read и друзьям, которые являются асинхронным средством ввода-вывода для доступа к файлам. Они довольно не переносятся и работают несколько раз в разы - поэтому большинство проектов фактически решили использовать отдельный процесс (или поток) для ввода-вывода и просто использовать блокировку IO там.

Опять же, может быть, вас интересует как-то "выбор": в файл, который вы получите, когда файл будет расти. Как вы, вероятно, поняли, что select, poll и т.д. Не работают. Большинство программ делают это просто путем опроса файла каждую секунду или около того - например, "tail -f" делает это волшебным путем опроса. Тем не менее, вы также можете заставить ядро ​​уведомлять вас, когда файл записывается, и это происходит с помощью inotify и друзей. Есть несколько удобных библиотек, которые обертывают все это для вас, поэтому вам не нужно гадать со спецификой самостоятельно. А именно, для python, inotifyx и pyinotify.