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

Понимание буферизации ввода-вывода в Ruby и OS

Как работает буферизация ввода-вывода в Ruby? Как часто данные сбрасываются в базовый поток при использовании классов IO и File? Как это соотносится с буферизацией ОС? Что нужно сделать, чтобы гарантировать, что данные были записаны на диск, прежде чем уверенно прочитать его для обработки?

4b9b3361

Ответ 1

Документация Ruby IO не на 100% понятна, как работает эта буферизация, но это то, что вы можете извлечь из документации:

  • Ruby IO имеет собственный внутренний буфер
  • В дополнение к этому базовая операционная система может или не может дополнительно буферизовать данные.

Соответствующие методы для просмотра:

  • IO.flush: Сбрасывает IO. Я также посмотрел на источник Ruby, и вызов IO.flush также вызывает базовую ОС fflush(). Этого должно быть достаточно для кэширования файла, но он не гарантирует физические данные на диске.
  • IO.sync=: если установлено значение true, внутренняя буферизация Ruby не выполняется. Все немедленно отправляется в ОС, и для каждой записи вызывается fflush().
  • IO.sync: возвращает текущую настройку синхронизации (true или false).
  • IO.fsync: Сбрасывает как буферы Ruby + вызовы fsync() в ОС (если он его поддерживает). Это гарантирует полную очистку вплоть до файла физического диска.
  • IO.close: Закрывает Ruby IO и записывает ожидающие данные в ОС. Заметим, что это не означает fsync(). Документация POSIX на close() говорит, что она НЕ гарантирует, что данные физически записаны в файл. Поэтому вам нужно использовать явный вызов fsync() для этого.

Заключение: flush и/или close должно быть достаточно, чтобы файл был кэширован, чтобы его можно было прочитать полностью другим процессом или операцией. Чтобы получить файл полностью на физическом носителе с уверенностью, вам нужно позвонить IO.fsync.

Другие связанные методы:

  • IO.syswrite: обходить внутренние буферы Ruby и делать прямую ОС write. Если вы используете это, не смешивайте его с IO.read/write.
  • IO.sysread: То же, что и выше, но для чтения.

Ответ 2

Ruby выполняет внутреннюю буферизацию поверх ОС. Когда вы делаете file.flush, Ruby очищает свой внутренний буфер. Чтобы файл записывался на диск, вам необходимо выполнить file.fsync. Но в конце концов вы не можете быть уверены, что файл записывается на диск в любом случае, это зависит от ОС, контроллера hdd и hdd.