Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Лекции_по_ОС / Буферный кэш

.doc
Скачиваний:
33
Добавлен:
03.03.2016
Размер:
1.59 Mб
Скачать

Буферный кэш

работа файловой подсистемы тесно связана с обменом данными с периферийными устройствами.

Для обычных файлов и каталогов — это устройство, на котором размещается соответствующая файловая система,

для специальных файлов устройств – это принтер, терминал, или сетевой адаптер.

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

Поскольку основные данные хранятся на дисковых накопителях, дисковый ввод/вывод является узким местом операционной системы.

Для повышения производительности дискового ввода/вывода и, соответственно, всей системы в целом, в UNIX используется кэширование дисковых блоков в памяти.

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

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

Схема взаимодействия различных подсистем ядра с буферным кэшем приведена на рис. 4.13.

Внутренняя структура буферного кэша

Буферный кэш состоит из буферов данных, размер которых достаточен для размещения одного дискового блока.

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

Заголовок также используется при обмене данными с драйвером устройства для выполнения фактической операции ввода/вывода.

Когда возникает необходимость чтения или записи буфера на диск, ядро заносит параметры операции ввода/вывода в заголовок и передает его функции драйвера устройства.

После завершения операции ввода/вывода заголовок содержит информацию о ее результатах.

Основные поля структуры buf приведены в табл. 4.9.

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

Например, с помощью флага b_busy осуществляется синхронизация доступа к буферу.

Флаг b_delwri отмечает буфер как модифицированный, или «грязный», требующий сохранения на диске перед повторным использованием.

Флаги b_read, b_write, b_async, b_done и b_error используются драйвером диска.

Буферный кэш использует механизм отложенной записи (write-behind), при котором модификация буфера не вызывает немедленной записи на диск.

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

Буферный кэш позволяет значительно уменьшить интенсивность записи на диск и реорганизовать последовательность записи отдельных буферов и повышения производительности ввода/вывода (например, уменьшая время поиска, группируя запись соседних дисковых блоков).

Недостатки может привести к нарушению целостности файловой системы в случае неожиданного останова ОС.

Операции ввода/вывода

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

Когда процессу требуется прочитать или записать данные он использует системные вызовы read(2) или write(2), направляя тем самым запрос файловой подсистеме.

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

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

Обычно используется схема чтения вперед (read-ahead), когда считываются не только запрашиваемые блоки, но и блоки, которые с высокой вероятностью могут потребоваться в ближайшее время (рис. 4.14, а). Таким образом, последующие вызовы read(2) скорее всего не потребуют дискового ввода/вывода, а будут включать лишь копирование данных из буферов в память процесса, — операция, которая, как отмечалось, обладает на несколько порядков большей производительностью (рис. 4.14, б—в). При запросе на модификацию блока изменения также затрагивают только буфер кэша. При этом ядро помечает буфер как "грязный" в заголовке buf (рис. 4.14, г). Перед освобождением такого буфера для повторного использования, содержимое должно быть предварительно сохранено на диске (рис. 4.14, д).

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

Не заблокированные буферы помечаются как свободные и помещаются в специальный список. Буферы в этом списке располагаются в порядке наименее частого использования (Least Recently Used, LRU). Таким образом, когда ядру необходим буфер, оно выбирает тот, к которому не было обращений в течение наиболее продолжительного промежутка времени. После того как работа с буфером завершена, он помещается в конец списка и является наименее вероятным кандидатом на освобождение и повторное использование. Поэтому, если процесс вскоре опять обратится к тому же блоку данных, операция ввода/вывода по-прежнему будет происходить с буфером кэша. С течением времени буфер перемещается в направлении начала очереди, но при каждом последующем обращении к нему, будет помещен в ее конец.

Основной проблемой, связанной с буферным кэшем, является «старение» информации, хранящейся в дисковых блоках, образы которых находятся в буферном кэше. Как следует из схемы работы кэша, большинство изменений затрагивают только данные в соответствующих буферах, в то время как дисковые блоки хранят уже устаревшую информацию. Разумеется в нормально работающей системе проблемы как таковой не возникает, поскольку в операциях ввода/вывода всегда используются свежие данные буферного кэша. Однако при аварийном останове системы, это может привести к потере изменений данных файлов, сделанных процессами не­посредственно перед остановом.

Для уменьшения вероятности таких потерь в UNIX имеется несколько возможностей:

Во-первых, может использоваться системный вызов sync(2), который обновляет все дисковые блоки, соответствующие "грязным" буфера. Необходимо отметить, что sync(2) не ожидает завершения операции ввода/вывода, таким образом после возврата из функции не гарантируется, что все "грязные" буферы сохранены на диске3.

Во-вторых, процесс может открыть файл в синхронном режиме (указав флаг О_SYNC в системном вызове ореn(2)). При этом все изменения в файле будут немедленно сохраняться на диске.

Наконец, через регулярные промежутки времени в системе пробуждается специальный системный процесс — диспетчер буферного кэша (в различных версиях UNIX его названия отличаются, чаще используется fsflush или bdflush). Этот процесс освобождает "грязные" буферы, сохраняя их содержимое в соответствующих дисковых блоках (рис. 4.14, д).

Кэширование в SVR4

Центральной концепцией в архитектуре виртуальной памяти SVR4 является изображение файлов. При этом подходе все адресное пространство может 6ьггь представлено набором отображений различных файлов в память. Действительно, в страницы памяти, содержащие кодовые сегменты, отображаются соответствующие секции исполняемых файлов. Процесс может задать отображение с помощью системного вызова mmap(2), при этом страницам памяти будут соответствовать определенные участки отображаемого файла. Даже области памяти, содержимое которых изменяется и не связано ни с каким файлом файловой системы, т. н. анонимные страницы, можно отобразить на определенные участки специального файла устройства, отвечающего за область свопинга (именно там сохраняются ано­нимные объекты памяти). При этом фактический обмен данными между памятью и устройствами их хранения, инициируется возникновением страничной ошибки. Такая архитектура позволяет унифицировать опера­ции ввода/вывода практически для всех случаев.

При этом подходе, когда процесс выполняет вызовы read(2) или write(2), ядро устанавливает отображение части файла, адресованного этими вызо­вами, в собственное адресное пространство. Затем эта область копируется в адресное пространство процесса. При копировании возникают странич­ные ошибки, приводящие в фактическому считыванию дисковых блоков файла в память. Поскольку все операции кэширования данных в этом слу­чае обслуживаются подсистемой управления памятью, необходимость в буферном кэше, как отдельной подсистеме, отпадает.

Соседние файлы в папке Лекции_по_ОС