Обнаружение записи страницы памяти в Windows и Linux

#c #linux #winapi #garbage-collection #memory-mapping

#c #linux #winapi #сбор мусора #отображение памяти

Вопрос:

В настоящее время я работаю над сборщиком мусора поколения. Это означает, что проходят только самые последние объекты, а выжившие объекты (= достижимые из известных корней) передаются в более старое поколение. Это работает нормально, когда объекты указывают на другие объекты того же или более старых поколений. Однако, когда более старые объекты указывают на более новые, и поскольку проходят только более новые объекты, указанные объекты будут собраны неправильно. Чтобы избежать этого, такие объекты помечаются и просматриваются явно во время каждой фазы GC.

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

Чтобы узнать, какие объекты более старых поколений указывают на более молодые поколения, я ищу способ прозрачного отслеживания изменений памяти. Для этого я использую защиту памяти и обработку сигналов / исключений. Страницы памяти доступны только для чтения, что приводит к возникновению сигнала / исключения всякий раз, когда они записываются, и в этом случае я снова устанавливаю защиту памяти на чтение-запись и регистрирую адрес где-нибудь для дальнейшей обработки, и по возвращении код, ответственный за исключение, возобновляется в обычном режиме. Таким образом, когда запускается GC, я знаю, где искать потенциальных родителей для обхода.

В Linux я использую комбинацию обработки сигналов mprotect / SIGSEGV. В Windows я намерен использовать VirtualProtect, но не нашел эквивалента обработки SIGSEGV. Итак, мои вопросы:

  1. Как бы вы это сделали в Windows? API обработки исключений кажется довольно запутанным.

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

Мой код написан на обычном C. В настоящее время мне требуется, чтобы вызывающий код явно помечал измененные объекты, но это утомительно и подвержено ошибкам, поэтому я ищу прозрачный способ сделать это.

Заранее спасибо, Фред

Комментарии:

1. Структурированная обработка исключений.

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

3. К сожалению, SEH требует 1. поддержки компилятора и 2. обертывания блоков try вокруг клиентского кода, поэтому он не подходит для моей цели. Однако это может сработать.

4. FWIW, высокопроизводительные виртуальные машины обычно перехватывают запись указателя при генерации машинного кода (например, в JIT) и генерируют код, который также записывает подсказку о грязной странице в специальный массив, потому что использование виртуальной машины для выполнения работы очень медленно.

Ответ №1:

GetWriteWatch идеально подходит для этого. Документация здесь

Комментарии:

1. Спасибо, это именно та функция, которую я ищу. Я знал об этой функции, но сначала быстро отклонил ее, потому что она требует XP и не работает для 32-разрядных приложений на 64-разрядном Itanium. Но поскольку альтернативы также требуют XP, я думаю, мне придется отказаться от поддержки Win2000.