четверг, 4 октября 2007 г.

Поглощение памяти...

Есть много различных алгоритмов динамического распределения памяти. Я для себя выбрал один в меру быстрый, но не буду сейчас углубляться в его тонкости. Сейчас я хотел рассказать об одной хитрости, которая позволит не создавать статически выделенную память до перехода в страничный режим.

Любая динамически выделяемая память выделяется блоками. И обычно у каждого блока есть заголовок.. но прежде, чем создать рабочий хип ядра нам необходимо провести ревизию системных ресурсов, и создать списки страниц... То есть память нам нужна еще до того, как ядро войдет в рабочий режим и обзаведется полновесным хипом. Но как это сделать?

Списки страниц могут занимать разное количество памяти. Это зависит от количества собственно памяти в системе. Необходимо создать временный хип, который сможет вместить в себя списки страниц и некоторую другую информацию, определяемую до перехода в страничный режим. Количество памяти нам любезно предоставляет GrUB.
И мы получаем размер, который для удобства округлим до страниц.

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

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

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

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

Вот собственно такие планы на хип нового ядра. На этом на сегодня все.