Главная » Ядро Linux » Буферный кэш

0

В операционной  системе  Linux больше  нет  отдельного  буферного  кэша.  В ядрах серии   2.2  существовало два отдельных кэша:   страничный и  буферный. В первом кэшировалисы страницы памяти, а в другом — буферы.  Эти  два кэша  не  были  объединены  между собой.  Дисковый  блок мог находиться  в обоих кэшах  одновременно.   Это требовало больших  усилий  по  синхронизации двух кэшированных копий,  не  говоря уже о  напрасной трате  памяти.

Так  было  в ядрах серии  2.2 и  более ранних,  но  начиная  с ядер  Linux серии  2.4

оба кэша  объединили  вместе.  Сегодня  существует только  один дисковый  кэш — страничный кэш.

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

Демон pdflush

Измененные  (dirty, "грязные") страницы памяти когда-нибудь должны быть записаны на диск. Обратная запись страниц памяти выполняется в  следующих двух  случаях.

• Когда объем свободной памяти  становится меньше определенного  порога, ядро должно записать измененные данные обратно на диск, чтобы  освободить память.

• Когда несохраненные данные хранятся в  памяти достаточно долго, то  ядро должно их записать на диск, чтобы гарантировать, что  эти данные не  будут  находиться в Несохраненном состоянии неопределенное время.

Эти два  типа записи имеют разные цели. В  более старых ядрах они выполнялись двумя разными потоками  пространства ядра (см. следующий раздел). Однако в  ядре

2.6   эту  работу выполняет  группа (gang4) потоков ядра pdflush , которые называются демонами фоновой обратной записи  (или просто потоками pdflush) . Ходят слухи, что   название pdflus h — это сокращение от  "dirty page flush" ("очистка  грязных  страниц"). Не обращайте внимание на это сомнительное название, давайте лучше более детально рассмотрим, для чего нужны эти процессы.

Во-первых, потоки pdflus h служат для записи измененных страниц на диск, когда  объем свободной памяти в  системе уменьшается до  определенного уровня. Цель такой фоновой записи— освобождение памяти,  которую занимают незаписанные страницы, в  случае недостатка физических страниц памяти. Уровень,  когда начинается обратная запись,  может быть сконфигурирован  с  помощью параметра dir ty_background_rati o  утилиты  sysctl . Когда объем свободной памяти становится меньше  этого порога,  ядро вызывает  функцию  wakeup_bdf lus h ()5    для перевода в состояние выполнения потока pdflush , который пыполняет функцию обратной записи измененных страниц памяти background_writeou t () . Эта функция получает один параметр, равный количеству страниц,  которые функция должна попытаться записать на диск.

Функция продолжает запись до  тех  пор, пока не выполнятся два  следующих условия.

• Указанное минимальное количество страниц записано на диск.

• Объем свободной  памяти  превышает  соответствующее значение  параметра dirty_background_ratio .

Выполнение  этих условий гарантирует,  что   демон pdf lus h выполнил свою работу  по предотвращению нехватки памяти. Если эти условия не выполняются,  то  обратная запись может остановиться только тогда,  когда демон pdflus h запишет на диск все  несохраненные страницы и для него больше не будет работы.

Во-вторых, назначение демона pdflus h — периодически переходить в  состояние выполнения (независимо от  состояния нехватки памяти) и записывать на диск очень

4 Слово "gang"  не являетс я жаргонным .  Этот терми н часто используется в компьютерных  науках, чтобы указать группу чего-либо, что может выполняться  параллельно.

5Да,     название функции не совсем верное. Должн о  было бы быть wakeup_pdflush  ().  В  следующем разделе  рассказано, откуда произошло  это название.

давно  измененные страницы памяти. Это  гарантирует, что  измененные страницы не будут находиться в  памяти неопределенное время.   При  сбоях  системы будут  потеряны  те страницы памяти,  которые не  были  сохранены на  диске, так  как  содержимое памяти после  перегрузки не  сохраняется.  Следовательно,  периодическая синхронизация  страничного кэша  с данными на диске  является важным делом.  При  загрузке системы инициализируется таймер, периодически возвращающий к выполнению поток  pdflush ,  который выполняет функцию wb_kupdat e () .  Эта  функция выполняет обратную   запись  данных,  которые были  изменены более  чем  dirty_expire_centi seс s   сотых  секунды тому назад.  После  этого  таймер  снова  инициализируется,  чтобы сработать   через   dirty_expire_centisec s  сотых  секунды.  Таким  образом  потоки pdflus h  периодически  возвращаются к  выполнению  и  записывают на  диск  все  измененные страницы, данные в которых  старше, чем  указанный лимит.

Системный  администратор может  установить эти  значения  с  помощью каталога

/proc/sys/vr n  и  утилиты   sysctl .   Втабл.    15.1  приведен список  всех  соответствующих  переменных.

Таблица 15.1 . Параметры для настройки демона pdflus h

Переменная                                           Описание

dirty_background_ratio dirty_expire_centisecs

dirty_ratio dirty_writeback_centisecs

laptop_mode

Объем свободной оперативной памяти, при котором демон pdflus h начинает обратную запись незаписанных данных

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

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

•  •  i

Насколько часто,  в сотых долях секунды, процесс bdflus h

возвращается к выполнению для обратной записи данных

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

Код   потока  pdflus h   находится  в   файла х  mm/page-writeback. c   и   fs /

fs-writeback.с .

Режим ноутбука

Режим   ноутбука  — это  специальная  политика обратной записи  страниц с  целью оптимизации  использования  батареи  и  продления  срока   ее  работы.   Это  делается путем  минимизации  активности жестких  дисков,  чтобы  они  оставались в  остановленном состоянии по  возможности долго.  Конфигурировать этот режим  можно  с помощью   файла   /proc/sys/vm/laptop_mode .  По  умолчанию  в  этом  файле   записано значение 0 и  режим  ноутбука  выключен. Запись значения  1  в  этот  файл  позволяет включить  режим   ноутбука.

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

диск.   Таким  образом демон  pdflus h  пользуется  тем  преимуществом,  что  диск  уже запущен,  а также  он  гарантирует,  что  в ближайшем будущем  диск  снова  запущен не будет.

Такое   поведение  имеет   смысл,  когда  параметры   dirty_expire_centisec s  и dirty_writeback_centisec s установлены  в  большие значения,  скажем  10  минут. При  таких  задержках обратной записи диск  запускается не  часто, а когда  он  все-таки запускается,  то  работа  в  режиме  ноутбука гарантирует,  что  этот  момент  будет  использован с максимальной эффективностью.

Во  многих  поставках ОС  Linux  режим   ноутбука автоматически  включается  и  выключается,  при  этом  также   могут  изменяться и  другие  параметры демона pbflush , когда  заряд  батареи   уменьшается.  Такое   поведение  позволяет  получать преимущества  от  режима  ноутбука при  работе   от  батареи   и  автоматически  возвращаться  к нормальному поведению,  когда  машина включается в электрическую сеть.

Демоныbdflushиkupdated

В  ядрах  серий  до  2.6  работа  потоков pdflus h  выполнялась двумя  другими   потоками   ядра  bdflus h  и  kupdated .

Поток пространства ядра  bdflus h  выполнял  фоновую обратную запись измененных  страниц,  когда  количество доступной памяти  становилось достаточно малым. Также   был  определен ряд  пороговых значений,  аналогично  тому  как  это  делается для  демона pdflush .  Демон   bdflus h  возвращался к  выполнению  с  помощью функции  wakeup_bdflus h ()  , когда  количество свободной  памяти  становилось меньше этих  пороговых значений.

Между  демонами  bdflus h  и  pdflus h  существует  два  главных   отличия.  Первое состоит в том, что  демон   bdflus h  был  всего  один,  а количество  потоков  pdflus h может  меняться динамически. Об  этом  более  подробно будет  рассказано в следующем  разделе.  Второе  отличие состоит в том, что демон  bdflus h  работал  с буферами, он  записывал на  диск  измененные  буферы. Демон   pdflus h  работает со  страницами, он записывает на диск  целые  измененные страницы памяти. Конечно, страницы памяти могут  соответствовать буферам,  но  единицей  ввода-вывода  является  целая страница памяти,  а не  один  буфер.   Это  дает  преимущество, поскольку работать  со страницами памяти проще, чем с буферами, так как  страница памяти — более  общий и более  часто  используемый объект.

Так  как  демон  bdflus h  выполнял  обратную запись,  только   когда  количество свободной памяти очень  сильно уменьшалось или  количество буферов было  очень  большим, то  был  введен  поток  ядра  kupdated , который периодически выполнял обратную  запись измененных страниц памяти. Он  использовался для  целей, аналогичных функции wb_kupdat e ()   демона pdflush .

Потоки bdflus h  и  kupdate d и  их функциональность сейчас   заменены потоками pdflush .

Предотвращение перегруженности:

для чего нужны несколько потоков

Один  из  главных   недостатков решения на  основе демона bdflus h  состоит в том, что  демон  bdflus h  имел  всего  один  поток  выполнения. Это  приводило к  возможности  зависания демона при  большом количестве операций обратной записи, когда

один   поток  демона bdflus h  блокировался  на  очереди запросов  ввода-вывода перегруженного устройства,  в  то  время   как  очереди запросов  других  устройств  могли быть  в  этот  момент сравнительно  свободными.  Если  система имеет  несколько дисков  и  соответствующую процессорную  мощность,  то  ядро  должно иметь   возможность  загрузить работой все  диски.  К  сожалению,  даже  при  большом  количестве данных, для  которых необходима обратная  запись,  демон  bdflus h  может  оказаться загруженным работой с  одной  очередью и  не  сможет  поддерживать все  диски  в нагруженном состоянии. Это  происходит потому, что  пропускная способность диском конечна и, к несчастью, очень  низкая. Если  только  один  поток  выполняет обратную запись страниц,  то  он  может  проводить много  времени в  ожидании одного  диска, так  как  пропускная способность диска  ограничена. Для  облегчения этой  ситуации ядру  необходима многопоточная  обратная запись.  В таком   случае  ни  одна  очередь запросов не  может  стать  узким  местом.

В  ядрах  серии   2.6  эта  проблема решается путем  введения  нескольких  потоков pdflush .  Каждый поток  самостоятельно выполняет обратную запись страниц памяти  на диск, что  позволяет различным потокам pdflus h работать  с разными очередями  запросов устройств.

Количество потоков изменяется в  процессе  работы   системы в  соответствии с простым алгоритмом. Если  все  существующие потоки  pdflus h  оказываются занятыми  в течение одной   секунды, то создается новый поток  pdflush .  Общее  количество потоков не  может  превышать значения константы MAX_PDFLUSH_THREADS,  которая по умолчанию равна  8. И  наоборот, если  поток  pdflus h находился в состоянии ожидания  больше одной  секунды, то он уничтожается. Минимальное количество потоков равно, по крайней мере, значению константы MIN_PDFLUSH_THREADS,  что по умолчанию  соответствует 2.  Таким образом, количество потоков pdflus h  изменяется динамически в зависимости от количества страниц, для  которых необходима обратная запись, и  загруженности этих  потоков.  Если  все  потоки pdflus h  заняты обратной записью, то создается новый поток. Это  гарантирует, что  ни  одна  из  очередей запросов  устройств не  будет  перегружена, в то  время  как  другие  очереди устройств не  так загружены и в них  тоже  можно выполнять обратную запись. Если  перегрузка предотвращается,  то  количество потоков pdflus h уменьшается,  чтобы  освободить память.

Вce  это  хорошо, но  что  если  все  потоки pdflus h  зависнут в  ожидании записи в одну и ту же  перегруженную очередь?   В этом  случае  производительность нескольких потоков pdflus h  не  будет  выше  производительности  одного   потока,  а количество занятой памяти станет  значительно большим. Чтобы  уменьшить такой  эффект, для потоков pdflus h  реализован  алгоритм предотвращения  зависания  (congestion avoidance).  Потоки активно  начинают обратную запись страниц для  тех очередей, которые  не  перегружены.  В  результате потоки  pdflus h  распределяют свою  работу  по разным очередям и  воздерживаются от  записи в  перегруженную  очередь.  Когда  все потоки pdflus h  заняты работой и  запускается новый поток,  то  это  означает,  что они  действительно заняты.

В связи   с усовершенствованием алгоритмов обратной записи страниц,  включая введение демона bdflush , ядро   серии   2.6  позволяет  поддерживать в  загруженном состоянии  значительно  большее количество дисков,  чем  в  более  старых  версиях ядер.  При   активной работе  потоки pdflus h  могут  обеспечить большую пропускную способность сразу  для  большого количества дисковых устройств.

Коротко о главном

В этой  главе был рассмотрен страничный кэш  и обратная запись  страниц. Было показано, как  ядро  выполняет все операции страничного ввода-вывода, как  операции  записи откладываются с помощью дискового кэша  и как данные  записываются на диск  с помощью группы  потоков пространства ядра  pdf lush.

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

Модули

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

рячего  подключения.

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

Источник: Лав,  Роберт. Разработка ядра  Linux, 2-е  издание. : Пер.  с англ.  — М.  : ООО  «И.Д.  Вильяме» 2006. — 448 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии