Ассемблер под Windows №33

Менеджер блочной памяти #3


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


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

А у вас память кончилась! Не смотря на то, что Windows почти всегда может выделить до 2,5 гигабайт памяти для процесса, проблему возможной нехватки памяти забывать нельзя! Эта проблема может быть легко решена, но пока мы не собираемся использовать такие огромные куски памяти, можно повременить с выбором решения проблемы.

А память-то дырявая! Когда мелкие куски памяти постоянно резервируются/освобождаются, то память обычно сильно фрагментируется. Это одна из самых больших проблем, её мы обсуждали при написании процедуры удаления. В нашем случае работу процедуры дефрагментации можно представить следующим образом: Представьте, что x карт лежат на столе рядом друг с другом. Для того, чтоб подвинуть карту нужно совершить четыре действия (найти карту, поднять карту, найти место для карты, положить карту). Мы вынимаем карту y из середины (y<x). Нам нужно чтоб оставшиеся карты образовали ряд без дырок, при чём осуществить это надо как можно за меньшее количество действий. Можно, конечно, просто покартно передвинуть ряд карт от y до x, но это займёт 4*(x-y) действий. Гораздо легче взять карту x и положить её на место карты y, это займёт лишь 4 действия. Естественно, это осуществимо только, если мы знаем, где лежала карта y.
Именно так работает наша процедура дефрагментации.

Что? Где? Когда? Наряду с тем, что блоки памяти должны хранить нужную нам информацию, они также должны хранить какую-то информацию об остальных блоках. В нашем случае мы используем иерархическую систему хранения блоков, существуют блоки "объектов" (как папка в Windows) и блоки "полигоны" (как файлы в папках), причём первые 28 байт каждого блока занимает информация об иерархической структуре.

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

Это, на мой взгляд, самые важные моменты, которые надо учитывать. Но пойдём дальше, и посмотрим, как можно тестировать наш менеджер памяти. Можно конечно создать что-нибудь очень умное, но в целях экономии времени предлагаю просто написать маленькую программу, которая просто добавляет 16001 блоков памяти (1 главный, остальные - его дочерние) а потом удаляет, например каждый второй с конца. При написании следует помнить, что главный блок должен быть GL_OBJECT и его нельзя удалить, функция вернет 0. Посмотрим, что же получится:
include kernel32.inc
include asmGLmem.inc
include Objects.inc
  386
  .model flat
  option casemap:none

_BSS SEGMENT public USE32 'bss'
Object  dd 32 dup(?)
MainObj dd ?
Handles dd 16000 dup(?)
_BSS ENDS

_TEXT SEGMENT public USE32 'code'
_start:
  null ebx
  mov Object, GL_OBJECT
  run asmGLmem_AddObject, offset Object, ebx
  mov MainObj, eax
  mov Object, GL_TRIANGLES
  null ecx
LoopAddObjects:
  run asmGLmem_AddObject, offset Object, MainObj
  mov dword ptr [ecx*4+offset Handles],eax
  inc ecx
  cmp ecx,16000
  jnz LoopAddObjects
  null ecx
LoopAddObjects2:
  run asmGLmem_DeleteObject, dword ptr [ecx*4+offset Handles]
  add ecx, 2
  cmp ecx,1600
  jnz LoopAddObjects2
  run ExitProcess, ebx
  end _start
_TEXT ENDS
Это всего лишь небольшой пример, однако использовав его я нашёл и исправил 11 ошибок в asmGLmem. Теперь я предлагаю Вам, используя подобные программы (любую другую последовательность добавления/удаления блоков) протестировать библиотеку. Подробности тут.


На сегодня это всё. Если есть какие вопросы, пишите. Пишите на Dark_Lord@RusFAQ.ru или Dark_Lord@land.ru. Предыдущие выпуски можно найти на сайте рассылки

Сайт управляется системой uCoz