Что происходит (на уровне ОС), когда я читаю / пишу файл? - PullRequest
4 голосов
/ 02 февраля 2011

Допустим, одна программа читает файл F.txt, а другая программа пишет в этот файл в тот же момент.

(Когда я думаю о том, как бы реализовать эту функцию, если бы я был системным программистом), я понимаю, что может быть двусмысленность в:

  1. что увидит первая программа?

  2. где вторая программа записывает новые байты? (т.е. записать «на месте» против записи в новый файл, а затем заменить старый файл новым)

  3. сколько программ могут одновременно записывать в один и тот же файл?

    .. а может, что-то не так очевидно.

Итак, мои вопросы:

  1. Каковы основные стратегии для чтения / записи файлов?

  2. какие из них поддерживаются в каких ОС (Windows, Linux, Mac OS и т. Д.)?

  3. это может зависеть от определенного языка программирования? (Я могу предположить, что Java может попытаться обеспечить некоторое унифицированное поведение на всех поддерживаемых ОС)

Ответы [ 3 ]

5 голосов
/ 02 февраля 2011

Для чтения одного байта требуется долгий путь от магнитной пластины / флэш-ячейки до локальной переменной Java.Это путь, по которому проходит один байт:

  1. Магнитная пластина / флэш-ячейка
  2. Внутренний буфер жесткого диска
  3. Шина SATA / IDE
  4. Буфер SATA / IDE
  5. шина PCI / PCI-X
  6. шина данных компьютера
  7. оперативная память компьютера через DMA
  8. OS Page-cache
  9. буфер чтения Libc, также известный как пространство пользователя fopen() буфер чтения
  10. локальная переменная Java

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

Это означает, что каждая операция чтения и записи из вашего кода Java выполняется из локального буфера и в ваш локальный буфер:

FileInputStream fis = new FileInputStream("/home/vz0/F.txt");

// This byte comes from the user space buffer.
int oneByte = fis.read();

Страница обычно представляет собой один блок объемом 4 КБ памяти.Каждая страница имеет некоторые специальные флаги и атрибуты, один из которых является «грязной страницей», что означает, что на странице есть некоторые измененные данные, не записанные на физический носитель.

Некоторое время спустя, когда ОС решает сброситьгрязные данные обратно на диск, он отправляет данные в противоположном направлении от того, откуда они пришли.

Всякий раз, когда два разных процесса записывают данные в один и тот же файл, в результате получается:

  • Невозможно, если файл заблокирован.Второй процесс не сможет открыть файл.
  • Не определено, если запись выполняется в одну и ту же область файла.
  • Ожидается, если работа выполняется в разных областях файла.

«Регион» зависит от размеров внутреннего буфера, которые использует ваше приложение.Например, в файл размером два мегабайта могут записываться два разных процесса:

  • Один на первые 1 КБ данных (0; 1024).
  • Другой на последних 1 КБdata (2096128; 2097152)

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

Многие транзакционные базы данных заставляют некоторые записи из локальных буферов ОЗУ назад на дисквыдача операции sync .Все данные, относящиеся к одному файлу, сбрасываются обратно на магнитные пластины или флэш-ячейки, эффективно гарантируя, что при сбое питания данные не будут потеряны.

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

Система Page Cache крайне важна для производительности в многозадачном защищенном режиме . ОС и все современные операционные системы (Windows NT и выше, Linux, MacOS, * BSD) поддерживают все эти функции.

1 голос
/ 02 февраля 2011
0 голосов
/ 02 февраля 2011

Стратегий может быть столько же, сколько и файловых систем. Обычно SO сосредотачивается на том, чтобы избежать операций ввода-вывода путем кэширования файла перед его синхронизацией с диском. Чтение из буфера позволит увидеть ранее сохраненные в нем данные. Таким образом, между программным и аппаратным обеспечением существует слой буферизации (например, MySQL движок MyISAM использует этот уровень)

JVM синхронизирует буферы дескриптора файла на диск при закрытии файла или когда программа вызывает метод, такой как fsync (), но буферы могут синхронизироваться также SO, когда они превышают определенные пороги. В JVM это, конечно, унифицировано на всех поддерживаемых ОС.

...