При использовании общей памяти каждый процесс может отображать общую область в другую область своего соответствующего адресного пространства. Это означает, что при хранении указателей в общей области вам необходимо сохранить их как смещения начала общего региона. К сожалению, это усложняет использование атомарных инструкций (например, если вы пытаетесь написать алгоритм блокировки без блокировки). а>). Например, предположим, что у вас есть куча узлов с подсчетом ссылок в общей памяти, созданных одним писателем. Модуль записи периодически атомарно обновляет указатель «p», чтобы он указывал на действительный узел с положительным счетчиком ссылок. Читатели хотят атомарно записывать 'p', потому что он указывает на начало узла (структуры), первый элемент которого является счетчиком ссылок. Поскольку p всегда указывает на действительный узел, увеличение счетчика ссылок является безопасным и делает безопасным разыменование 'p' и доступ к другим членам. Однако все это работает только тогда, когда все находится в одном адресном пространстве. Если узлы и указатель 'p' хранятся в разделяемой памяти, клиенты страдают от состояния гонки:
- х = читать р
- у = х + смещение
- Увеличение счетчика ссылок в y
Во время шага 2 p может измениться, и x может больше не указывать на действительный узел. Единственный обходной путь, который я могу придумать, - это каким-то образом заставить все процессы договориться о том, где отображать общую память, чтобы в области mmap'd могли храниться настоящие указатели, а не смещения. Есть ли способ сделать это? Я вижу MAP_FIXED в документации mmap, но не знаю, как выбрать безопасный адрес.
Изменить: используя встроенную сборку и префикс «блокировка» на x86, возможно, можно создать «приращение ptr X со смещением Y по значению Z»? Эквивалентные варианты на других архитектурах? Не написал много сборки, не знаю, существуют ли необходимые инструкции.