Зная, какие страницы памяти были доступны во время выполнения - PullRequest
1 голос
/ 24 июля 2011

В моей программе мне нужно знать, к каким страницам программа периодически обращается, поэтому через каждые 0,5 или 1 секунду я проверяю, к каким страницам обращались, и вычисляю контрольную сумму по этим значениям страниц.

Я использую функцию mprotect, чтобы отметить области памяти, которые необходимо увидеть, и устанавливаю обработчик сигнала SIGSEGV для каждого потока.В начале каждого периода я устанавливаю защиту на PROT_READ, а затем, когда происходит сбой страницы, я даю доступ как к чтению, так и к записи после того, как запомнил ее адрес.

Однако я заметил, что этот метод делает выполнение моей программы довольно медленным.Кроме того, поскольку я делаю это для каждого потока, это еще больше снижает производительность.Есть ли способ сделать эту процедуру быстрее.В частности, возможно ли сделать это на уровне процесса, поэтому, например, если поток A вызывает ошибку страницы, он дает запись на эту страницу, а когда поток B обращается к ней, он уже имеет разрешения на запись.

1 Ответ

2 голосов
/ 24 июля 2011

Для более быстрого метода может быть создан специальный проход компилятора.Это обеспечит доступ к памяти инструмента с изменением флага в теневой памяти.Например, для каждой операции чтения или записи проход компилятора добавит специальную операцию записи в некоторую область, специфичную для потока (теневую память).

Существует проект http://code.google.com/p/address-sanitizer/, который работает как дополнительный проход кКомпилятор LLVM.Дополнительная память (теневая память) в 8 раз меньше используемой памяти.AddressSanitizer использует этот проход для обнаружения обращений к неинициализированной памяти: http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerAlgorithm Замедление составляет всего 1,5x-3x.Для разметки страниц по страницам теневая память будет очень маленькой (1-4 байта тени для 4096 байтов обычной памяти).

Если вы не хотите делать это в компиляторе или не можете этого сделать(например, приложения с закрытым исходным кодом), вы можете использовать существующую технику COW из ядра: http://en.wikipedia.org/wiki/Copy-on-write Ядро делает COW для каждой вилки через флаги доступа к памяти.Вы можете разветвить процесс в момент времени t1, остановить дочерний процесс, подождать 1 или 2 секунды, а затем сравнить сопоставления остановленного дочернего элемента (в нем нет записей, поэтому отображение такое же, как было в момент t1) и вашего процесса (измененные страницы).переназначены).Этот вариант быстрее, но он дает информацию только о записи, а не о действиях каждого потока.

Также вы можете взломать обработчик ошибок страницы COW в ядре.Этот хак будет сложнее, но он будет содержать информацию о том, какой поток сделал запись.

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