Атрибуты
защиты, перечисленные в предыдущей таблице, достаточно понятны, кроме двух
последних: PAGE_WRITECOPY и PAGE_EXECUTE_WRITECOPY. Они предназначены специально
для экономного расходования оперативной памяти и места в страничном файле.
Windows поддерживает мехянизм, позволяющий двум и более процессам разделять
один и тот же блок памяти. Например, если Вы запустите 10 экземпляров программы
Notepad, все экземпляры будут совместно использовать одни и те же страницы с
кодом и данными этой программы. И обычно никяких проблем не возникает — пока
процессы ничего не записывают в общие блоки памяти. Только представьте, что
творилось бы в системе, если потоки из разных процессов начали бы одновременно
записывать в один и тот же блок памяти!
Чтобы
предотвратить этот хаос, операционная система присваивает общему блоку памяти
атрибут защиты "копирование при записи" (copy-on-write). Когда поток
в одном процессе попытается что-нибудь записать в общий блок памяти, в дело тут
же вступит система и проделает следующие операции:
Найдет свободную страницу в оперативной памяти. Заметьте, что при
первом проецировании модуля на адресное пространство процесса эта страница
будет скопирована на одну из страниц, выделенных в страничном файле.
Поскольку система выделяет нужное пространство в страничном файле еще при
первом проецировании модуля, сбои на этом этапе маловероятны.
Скопирует страницу с данными, которые поток пытается записать в
общий блок памяти, на свободную страницу оперативной памяти, полученную на
этапе 1. Последней присваивается атрибут защиты PAGE_WRITECOPY или
PAGE_EXECUTE_WRITECOPY. Атрибут защиты и содержимое исходной страницы не
меняются.
Отобразит виртуальный адрес этой страницы в процессе на новую
страницу в оперативной памяти.
Когда
система выполнит эти операции, процесс получит свою копию нужной страницы
памяти.
Кроме
того, при резервировании адресного пространства или передаче физической памяти
через VirtualAlloc нельзя указывать атрибуты PAGE_WRITECOPY или
PAGE_EXECUTE_WRITECOPY. Иначе вызов VirtualAlloc даст ошибку, a GetLastError вернет код
ERROR_INVALID_PARAMETER. Дело в
том, что эти два атрибута используются операционной системой, только когда она
проецирует образы EXE- или DLL-файлов.