Глава про архитектуру памяти в Windows у Рихтера дала больше вопросов чем ответов ))). Если поведение системы при динамическом выделении памяти более-менее понятно (хотя и тут приходится строить некоторые предположения, см. ниже), то поведение при загрузке и выполнении исполняемых модулей - один большой вопрос ). Вот динамика (VirtualAlloc, etc) При выделении региона памяти, сначала происходит резервирование АП под этот регион (те система резервирует некоторый диапазон адресов под наши нужды, эти адреса не будут использованы системой пока мы не освободим регион или не завершится процесс его зарезервировавший) в соответствии с гранулярностью и размером страницы. После чего система передает под этот регион часть физической памяти(не под весь регион; далее память будет передаваться по необходимости, посредством перехвата page fault(?)). Как я понял первоначально эта передаваемая физическая память находится в страничном файле (?). И только при обращении потока к выделенной памяти (в виртуальном АП) страница(ы) подкачиваются из страничного файла в оперативную память и адреса в АП проецируются на физические адреса (?). В случае же если страничный файл отсутствует память передается из оперативной сразу (?). Ну и далее механизм обращения\подкачки\вытеснения понятен в принципе из графика в книге. А вот когда загружается исполняемый модуль ... Во-первых как я понял для подкачки используется сам файл модуля. Как я понимаю из изучения PE-формата файл на диске != файлу в памяти, таким образом загрузчик должен полностью скопировать и настроить все секции исполняемого файла в оперативную память, причем по Рихтеру в страничном файле место не резервируется и он первоначально не используется(только если секция была изменена, тк на них вешается аттрибут PAGE_WRITECOPY). Но каким же образом система узнает в случае если страница была вытеснена из оперативной памяти, что нужно взять из файла, если эта страница опять понадобилась? Или гдето в недрах ФС хранится образ файла в памяти и уже его используют для подкачки? Сорри за много букв, но перечитывание уже не помагает (. ЗЫ Гугл тоже не помог, MSDN похоже эти вопросы не затрагивает (насколько я понял с моим английским), всетаки книга Рихтера лучшая под ring3 )))
Ты делаешь VirtualAlloc(Ex)/ZwAllocateVirtualMemory - происходит резервирование адресов нужного диапазона. В соответствующие таблицы страниц записывается Demand-Zero PTE, это значит, что фактически страницы не выделяются, а при первом обращении к ним сработает исключение ошибки страницы #PF и операционной системе нужно будет выделить страницу и обнулить ее, затем передать процессу. То есть первоначально ничего не передается никуда, страничные файлы тут вообще не при чем. Квота с процесса, конечно, взымается, чтобы он не запросил страниц больше, чем есть свободных. Страничный же файл используется тогда и только тогда, когда системе нужны свободные страницы (при их нехватке). Тогда происходит усечение рабочего набора процесса, страницы переводятся в состояние Transition (это значит, что они уже отобраны у процесса, но еще не скинуты в своп и не освобождены), а нужное число страниц из Transition переводятся в состояние Paged-Out (скидываются на диск, если они модифицированы, освобождаюися соотв. физстраницы и передаются другому процессу). Когда первый процесс вновь обращается к Transition странице, операционной системе нужно лишь вернуть ее процессу - она еще не сброшена в страничный файл. Когда происходит обращение к Paged-Out странице, идет попытка выделения физстраницы и чтения туда соответствующего содержимого страничного файла. Для исполняемых модулей и вообще для проецированных файлов дело обстоит так. Да, для "подкачки" (если это можно так назвать) используется сам проецируемый файл, точнее, если он проецируетс только на чтение, то при необходимости усечения рабочего набора система просто уничтожает страницу (нет необходимость что-либо куда-либо записывать). При повторном обращении она будет вновь считана из файла. Если файл проецируется для чтения/записи, то при усечении рабочего набора страница скидывается сначала на диск, если она модифицирована. Если нет, то все происходит аналогично мапированию только на чтение. Загрузчику не требуется ничего копировать, он просто проецирует соответствующие места файла в соответствующие регионы виртуального адресного пространства процесса. Страницы поддерживаются (на языке оригинала это называется backed by) этим файлом. Эти страницы шарятся между всеми процессами, которые используют этот файл. Другое дело, когда на страницу выставляются атрибуты на запись (VirtualProtect), а сам файл спроецирован как write-copy. Тогда процессу выдается частная копия страницы, поддерживаемая файлом подкачки, а остальные процессы, конечно же, "видят" немодифицированную версию этой страницы. Остальные немодифицировнные страницы файла продолжают поддерживаться исходным файлом. Надеюсь, описал доступно.