Можете ли вы вызвать сбой, если запись происходит в заданную область памяти с более тонкой, чем детализация страницы? - PullRequest
2 голосов
/ 21 марта 2010

Я пишу программу, которая из соображений производительности использует разделяемую память (сокеты и каналы в качестве альтернатив были оценены, и они недостаточно быстры для моей задачи, вообще говоря, любой метод IPC, который включает в себя копии, слишком медленный). В области общей памяти я пишу много структур фиксированного размера. Существует одна программа, отвечающая за запись структур в общую память, и множество клиентов, которые читают из нее. Однако в каждой структуре есть один член, в который клиенты должны писать (счетчик ссылок, который они будут обновлять атомарно). Все остальные участники должны быть доступны только для клиентов.

Поскольку клиентам необходимо изменить этого одного члена, они не могут сопоставить область общей памяти только для чтения. Но они также не должны возиться с другими участниками, и, поскольку эти программы написаны на C ++, возможно повреждение памяти. В идеале, одному клиенту должно быть как можно сложнее разбить другого. Я беспокоюсь только о клиентах с ошибками, а не о вредоносных, поэтому допускаются несовершенные решения.

Я могу попытаться остановить перезапись клиентов, объявив элементы в заголовке, которые они используют как const, но это не предотвратит перезапись памяти (переполнение буфера, неправильное приведение и т. Д.). Я могу вставить канареек , но тогда мне придется постоянно оплачивать стоимость их проверки.

Вместо того, чтобы хранить элемент счетчика ссылок напрямую, я мог бы хранить указатель на фактические данные на отдельной отображенной странице только для записи, сохраняя структуры в отображаемых страницах только для чтения. Это будет работать, ОС вызовет сбой моего приложения, если я попытаюсь записать данные, на которые указывает указатель, но косвенное хранение может быть нежелательным при попытке написать алгоритмы без блокировки , потому что нужно следовать другому уровню косвенность может измениться, может ли что-то быть сделано атомарно.

Есть ли способ пометить меньшие области памяти так, что их запись приведет к взрыву вашего приложения? У некоторых платформ есть аппаратные точки наблюдения, и, возможно, я мог бы активировать одну из них со встроенной сборкой, но я бы ограничился только 4 на 32-битном x86 за раз, и каждая могла покрывать только часть структуры, потому что они ограничены до 4 байтов. Это также сделало бы мою программу болезненной для отладки;)

Редактировать: я нашел эту довольно сногсшибательную бумагу , но, к сожалению, она требует использования памяти ECC и модифицированного ядра Linux.

Ответы [ 3 ]

6 голосов
/ 21 марта 2010

Я не думаю, что можно сделать так, чтобы несколько битов читались только на уровне ОС.

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

long *refCountersBase;//The start address of the ref counters page
MyStruct *structsBase;//The start address of your structures page

//get address to reference counter
long *getRefCounter(MyStruct *myStruct )
{
    size_t n = myStruct - structsBase;
    long *ref = refCountersBase + n;
    return ref;
}
1 голос
/ 21 марта 2010

Я никогда не слышал о применении режима «только чтение» при степени детализации страницы, поэтому вам может не повезти в этом направлении, если вы не можете поместить каждую структуру на две страницы. Если вы можете позволить себе две страницы на структуру, вы можете поместить счетчик ссылок на одну из страниц, а другую сделать доступным только для чтения.

Вы можете написать API, а не просто использовать заголовки. Принуждение клиентов к использованию API устранит большинство проблем с коррупцией.

Хранение данных с количеством ссылок, а не на другой странице, поможет с локализацией данных и тем самым улучшит производительность кэша.

Вам необходимо учесть, что у читателя может быть проблема и он не может правильно обновить счетчик ссылок. Кроме того, что автор может не завершить обновление. Справиться с этими вещами требует дополнительных проверок. Вы можете комбинировать такие проверки с API. Возможно, стоит поэкспериментировать, чтобы измерить влияние на производительность какой-либо проверки целостности. Может быть достаточно быстро сохранить контрольную сумму, что-то такое же простое, как adler32.

1 голос
/ 21 марта 2010

Вам потребуется добавить обработчик сигнала для SIGSEGV, который восстанавливается из исключения, но только для определенных адресов.Отправной точкой может быть http://www.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html и соответствующая документация для вашей ОС.

Редактировать: Я считаю, что вы хотите выполнить запись и возврат, если адрес записина самом деле все в порядке и вызовите предыдущий обработчик исключений (указатель, который вы получаете при установке обработчика исключений), если хотите распространить исключение.Хотя я не разбираюсь в этих вещах.

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