Windows для профессионалов


Статические данные не разделяются несколькими экземплярами EXE или DLL


Когда Вы создаете новый процесс для уже выполняемого приложения, система про сти открывает другое проецируемое в память представление (view) объекта "проек ция файла" (file-mapping object), идентифицирующего образ исполняемого файла, и создает новые объекты "процесс" и "поток" (для первичного потока) Этим объектам присваиваются идентификаторы процесса и потока. С помощью проецируемых в память файлов несколько одновременно выполняемых экземпляров приложения мо жет совместно использовать один и тот же код, загруженный в оперативную память. Здесь возникает небольшая проблема. Процессы используют линейное (flat) ад ресное пространство. При компиляции и компоновке программы весь ее код и дан ные объединяются в нечто, так сказать, большое и цельное Данные, конечно, отделе ны от кода, но только в том смысле, что они расположены вслед за кодом в ЕХЕ-фай ле<snoska На самом деле содержимое файла разбито на отдельные разделы (sections). Код находится в одном разделе, а глобальные переменные — в другом Разделы выравниваются по грани цам страниц Приложение определяет размер страницы через функцию GetSystemInfo. В EXE- или DLL-флйле раздел кода обычно предшествует разделу данных.

>. Вот упрощенная иллюстрация того, как код и данные приложения загружаются в виртуальную память, а затем отображаются на адресное пространство процесса:

Теперь допустим, что запущен второй экземпляр программы. Система просто-на просто проецирует страницы виртуальной памяти, содержащие код и данные файла, на адресное пространство второго экземпляра приложения:

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

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





Система выделяет новую страницу и копирует на нее содержимое страницы дан ных 2. Адресное пространство первого экземпляра изменяется так, чтобы отобразить новую страницу данных на тот же участок, что и исходную. Теперь процесс может изменить глобальную переменную, не затрагивая данные другого экземпляра .

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

WINDOWS 98
При загрузке процесса система просматривает все страницы образа файла. Физическая память из страничного файла передается сразу только тем стра ницам, которые должны быть защищены атрибутом копирования при записи. При обращении к такому участку образа файла в память загружается соответ ствующая страница. Если cc модификации не происходит, она может быть выгружена из памяти и при необходимости загружена вновь. Если же страни ца файла модифицируется, система перекачивает ее на одну из ранее передан ных страниц в страничном файле.

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


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