Как ядрото управлява паметта

По-рано видяхме как е организирана виртуалната памет на процеса. Сега нека да разгледаме механизмите, чрез които ядрото управлява паметта. Нека се обърнем към нашата програма:

управлява

В Windows блокът EPROCESS е приблизително нещо средно между структурите task_struct и mm_struct. Аналог на дескриптора на областта на виртуалната памет е дескрипторът на виртуалния адрес или VAD, информацията за тези дескриптори се съхранява в дървото на AVL. Знаете ли кое е най-смешното в сравнението на Windows и Linux? Просто разликите не са толкова много.

Защитата на паметта се извършва на базата на страница, тъй като страницата е най-малкото "парче" памет, за което могат да бъдат зададени флаговете "U/S" и "R/W". Трябва обаче да се има предвид, че теоретично две различни виртуални страници с различен набор от флагове могат да съответстват на една и съща физическа страница. Имайте предвид, че форматът на таблицата със страници на записа не предоставя флагове, свързани със забраната за изпълнение на код. Ето защо класическото x86 пейджинг не пречи на изпълнението на кода в стека, което улеснява използването на уязвимости въз основа на препълване на буфера в стека (неизпълнимите стекове все още са обект на уязвимости, в този случай се използва техниката за връщане към libc и други трикове). Липсата на флага за забрана на изпълнение също показва друг важен аспект: флаговете за достъп, съдържащи се във VMA дескриптора, не винаги имат пряко съответствие в системата за защита, реализирана от процесора, и могат да съответстват на тази система само в по-голяма или по-малка степен. Образно казано, ядрото дава всичко от себе си, но в крайна сметка архитектурата на процесора налага своите ограничения върху това, което може да се реализира.

страници

Ядрото на Linux следи всяка рамка на страница със специалендескриптор и някои флагове. Взети заедно, тези дескриптори описват цялата RAM на компютъра; във всеки един момент е известно точното състояние на всяка страница. Управлението на физическата памет се основава на алгоритъма за разпределение на паметта Buddy. По този начин рамката на страницата се счита за свободна, ако е достъпна за избор от гледна точка на алгоритъма Buddy. Разпределената за използване страница-рамка може да бъде „анонимна“ (в този случай съдържа програмни данни) или да се намира в т.нар. кеш на страници (кеш на страници) и съхраняват част от данните от някакъв файл или блоково устройство. Има и други, по-екзотични приложения за рамки за страници, но нека ги оставим настрана засега. Windows има подобна структура за следене на рамки на страници и се нарича база данни с номера на рамки на страници. Сега нека обединим всички тези концепции – области на виртуална памет (VMA), таблици на страници и рамки на страници – и да видим как работи. Следното е пример за купчина в потребителското пространство на програмата:

паметта

Правоъгълници със син фон представляват виртуални страници, които са в областта на виртуалната памет. Стрелките показват записи в таблицата на страниците, с помощта на които виртуалните страници се „картографират“ в рамки на страници (физически страници). Някои виртуални страници нямат стрелки; това означава, че техните съответни записи в таблицата на страниците имат флаг за присъствие, зададен на 0. Това може да се дължи на факта, че въпросните виртуални страници може да не са били използвани никога преди или защото съответните физически страници са били заменени. Във всеки случай опитът за достъп до тези страници ще доведе до грешка на страницата, въпреки че виртуалните страници са в рамките на някаква VMA. Може да изглежда странно, чеима такъв вид несъответствие - страници в рамките на VMA и въпреки това достъпът до тях е невалиден - но това наистина често се случва.

VMA е вид "договор" между програмата и ядрото. Искате от ядрото да направи нещо (като разпределяне на памет или карта на файл), ядрото казва „няма проблем“ и създава нов или актуализира съществуващ VMA. Но в същото време ядрото не бърза да изпълни самата заявка, вместо това ядрото ще отложи незабавното изпълнение на исканото действие, докато не възникне грешка на страницата. Да, оказва се, че ядрото е един вид „мързелив негодник“; това е основният принцип на управлението на виртуалната памет. Този принцип се прилага в повечето ситуации - някои от тях може да са доста познати, други - неочаквани, но общото правило е, че VMA улавя само това, което е договорено, докато записите в таблицата на страниците отразяват това, което е директно направено от мързеливото ядро. Тези две структури участват заедно в управлението на програмната памет; и двете структури играят роля при обработката на грешки в страницата, освобождаване на памет, размяна на страници и т.н. Помислете за прост случай на разпределение на паметта:

страници

Да кажем, че VMA все още се намира. По-нататъшната обработка на грешка в страницата е както следва - ядрото преглежда съдържанието на записа в таблицата на страниците и типа VMA. В нашия пример записът в таблицата на страниците показва, че няма страница в паметта. Освен това нашият запис е напълно празен (състои се от всички нули), а в Linux това означава, че съответната виртуална страница изобщо не е била картографирана. Тъй като имаме работа с „анонимен“ VMA, тогава всички по-нататъшни действия ще бъдат свързани само с RAM и за справяне с тази ситуация,функция do_anonymous_page(). Тази функция избира рамка на страница и картографира виртуална страница в нея чрез въвеждане на необходимите данни в записа на таблицата на страниците.

Въпросът можеше да бъде и друг. Записът в таблицата на страниците за разменена страница, например, има флаг за присъствие, зададен на нула, но останалата част от записа не е празна. Останалите битове съхраняват информация за страницата, която е в размяната. Функцията do_swap_page() чете съдържанието на тази страница от диска и я зарежда в RAM - този тип грешка на страницата се нарича основна грешка.

Това завършва първата част от нашата екскурзия в това как ядрото управлява паметта. В следващата статия ще усложним картината, като я разширим с файлови операции, така че да имаме пълно разбиране на основните концепции за управление на паметта, включително някои аспекти на производителността.