Windows

         

В какой момент региону передают физическую память


Допустим, Вы разрабатываете программу — электронную таблицу, которая поддержи ваетдо 200 строк при 256 колонках Для каждой ячейки необходима своя структура CELLDATA, описывающая ее (ячейки) содержимое. Простейший способ работы с двух мерной матрицей ячеек, казалось бы, — взять и объявить в программе такую пере менную:

CELLDATA CellData[200][256];

Но если размер структуры CELLDATA будет хотя бы 128 байтов, матрица потребу ет 6 553 600 (200 * 256 * 128) байтов физической памяти. Не многовато ли? Тем более что большинство пользователей заполняет данными всего несколько ячеек Выходит, матрицы здесь крайне неэффективны

Поэтому электронные таблицы реализуют на основе других методов управления структурами данных, используя, например, связанные списки В этом случае структу ры CELLDATA создаются только для ячеек, содержащих какие-то данные И поскольку большая часть ячеек в таблице остается незадействованной, Вы экономите колоссаль ные объемы памяти Но это значительно усложняет доступ к содержимому ячеек. Что бы, допустим, выяснить содержимое ячейки на пересечении строки 5 и колонки 10, придется пройти по всей цепочке связанных списков В итоге метод связанных спис ков работает медленнее, чем метод, основанный на объявлении матрицы.

К счастью, виртуальная память позволяет найти компромисс между «лобовым» объявлением двухмерной матрицы и реализацией связанных списков. Тем самым можно совместить простоту и высокую скорость доступа к ячейкам, предлагаемую "матричным" методом, с экономным расходованием памяти, заложенным в метод связанных списков.

Вот что надо сделать в своей программе.

  • Зарезервировать достаточно большой регион, чтобы при необходимости в него мог поместиться весь массив структур CELLDATA. Для резервирования региона физическая память не нужна

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




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

  • Инициализировать элементы новой структуры CELLDATA.


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

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

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

    Определить, надо ли передавать физическую память части региона, можно четырь мя способами

  • Всегда пытаться передавать физическую память Вместо того чтобы проверять, отображен данный участок региона на физическую памягь или нет, заставьте программу передавать память при каждом вызове функции VirtualAlloc. Ведь система сама деласт такую проверку и, если физическая память спроецирова на на данный участок, повторной передачи не допускает. Это простейший путь, но при каждом изменении структуры CELLDATA придется вызывать функцию VirtualAlloc, что, естественно, скяжстся на скорости работы программы



  • Определять (с помощью VirtualQuety), передана ли уже физическая память ад ресному пространству, содержащему структуру CELLDATA. Если да, больше ничего не делать, нет — вызвать VirtuaiAlloc для передачи памяти Этот метод на деле еще хуже, чем первый он не только замедляет выполнение, но и уве личивает размер программы из-за дополнительных вызовов VirtualQuery.

  • Вести учет, каким страницам передана физическая память, а каким — нет Это повысит скорость работы программы Вы избежите лишних вызовов VirtualAlloc, а программа сможет — быстрее, чем система — определять, передана ли память. Недостаток этого метода в том, что придется отслеживать передачу страииц; иногда это просто, но может быть и очень сложно ~ все зависит от конкретной задачи.

  • Самое лучшее — использовать структурную обработку исключений (SEH). SEH — одно из средств операционной системы, с помощью которого она уве домляет приложения о возникновении определенных событий. В общем и целом, Вы добавляете в программу обработчик исключений, после чего любая попытка обращения к участку, которому не передана физическая память, зас тавляет систему уведомлять программу о возникшей проблеме. Далее програм ма передает память нужному участку и сообщает системе, что та должна по вторить операцию, вызвавшую исключение. На этот раз доступ к памяти прой дет успешно, и программа, как ни в чем не бывало, продолжит работу. Таким образом, Ваша задача заметно упрощается (а значит, упрощается и код); кро ме того, программа, не делая больше лишних вызовов, выполняется быстрее. Но подробное рассмотрение механизма структурной обработки исключений мы отложим до глав 23, 24 и 25. Программа-пример Spreadsheet в главе 25 про демонстрирует именно этот способ использования виртуальной памяти.



  • Содержание раздела