Используйте VirtualProtect, чтобы пометить страницы как копии при записи (разветвление для Windows) - PullRequest
7 голосов
/ 27 февраля 2011

Я использую VirtualAlloc (Ex) для выделения и фиксации большого диапазона страниц.

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

Можно ли это сделать с помощью VirtualAlloc (Ex) и VirtualProtect (Ex)?

Это тривиально в системах posix благодарявилка ().Могу ли я эффективно эмулировать только эту часть форка на Windows?

Спасибо, -Dan

Ответы [ 2 ]

4 голосов
/ 18 марта 2011

Не думаю, что что-то из этого вполне отвечает на вопрос, заданный оригинальным постером. Возможно, я рискну следующий пример. Предположим, у кого-то есть данные в «bufferA», а кто-то копирует их в «bufferB», а затем модифицирует оба буфера. Теперь проверяются оба буфера и решается скопировать «bufferA» или «bufferB» в «bufferC» и внести дополнительные изменения в «bufferC» и т. Д.

Предполагая, что буферы велики, а модификации малы, вопрос заключается в том, будет ли оптимизирована использование возможности MMU «копировать при записи» на хост-машине, и существует ли API, позволяющий это сделать. .

Использование файлов с отображением в памяти не совсем работает, потому что, как только вы используете PAGE_WRITECOPY, кажется, нет никакого способа сказать «теперь скопируйте виртуальные страницы, содержащие изменения». Например, если «bufferA» и «bufferB» оба были сопоставлениями одного и того же файла, и во время сопоставления одно из них было помечено «WRITECOPY», то, похоже, нет способа отобразить эти модификации в «bufferC». Конечно, можно просто скопировать биты, но вопрос в том, возможна ли оптимизация.

Существует функция VirtualCopy (), но, похоже, она специфична для Windows CE и работает с физическими адресами. Вопрос здесь в том, есть ли что-то вроде «VirtualCopy», но в качестве источника используется виртуальный адрес.

Обратите внимание, что хотя "fork ()" (в системах, в которых он есть) делает это, один "форк" выполняет весь процесс, а не только буфер. Здесь была связанная с этим дискуссия, касающаяся «memcpy при копировании при записи» ( Могу ли я сделать memcpy при записи при записи в Linux? ).

Таким образом, искомый API может выглядеть примерно так: void * VirualCopyVirtualAddressSpace (void * src, size_t length);

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

1 голос
/ 28 февраля 2011

Я думаю, что вы можете сделать это, если вы используете отображение памяти (CreateFileMapping / MapViewOfFile) с PAGE_WRITECOPY.

Этот пример в MSDN может служить отправной точкой, если вы измените FILE_MAP_ALL_ACCESS на PAGE_WRITECOPYдля второго процесса.

Если вам нужно согласованное поведение копирования на определенный момент времени, вам, вероятно, потребуется VirtualProtect () отображенной области с PAGE_WRITECOPY в первом процессе, поэтому второй процесс не видит никакихизменения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...