Подтвердить что ты не робот

Является ли boost:: interprocess готовым к прайм-тайм?

Я работал над потоковой безопасной очередью, поддерживаемой файлами с отображением памяти, которые довольно интенсивно использовали interprocess. Я отправил его для обзора кода, а разработчик с большим опытом, чем у меня на этой планете, сказал, что он не чувствует, что boost:: interprocess был "готов к прайм-тайм" и что я должен просто использовать pthreads напрямую.

Я думаю, что в основном FUD. Я лично считаю, что это смехотворно переделывать такие вещи, как upgradeable_named_mutex или boost:: interprocess:: deque, но мне любопытно узнать, что думают другие люди. Я не мог найти никаких данных, чтобы поддержать его требование, но, возможно, я просто неинформирован или наивен. Stackoverflow просветит меня!

4b9b3361

Ответ 1

Я попытался использовать boost:: interprocess для проекта и ушел со смешанными чувствами. Мое основное недоумение - это дизайн boost:: offset_ptr и то, как он обрабатывает значения NULL - короче говоря, boost:: interprocess может сделать диагностику ошибок NULL-указателей очень болезненными. Проблема в том, что сегмент разделяемой памяти отображается где-то посередине адресного пространства вашего процесса, а это означает, что "NULL" offset_ptr, когда разыменовывается, укажет на допустимую ячейку памяти, поэтому ваше приложение не будет segfault. Это означает, что когда ваше приложение, наконец, сработает, оно может быть слишком долго после ошибки, что очень сложно отладить.

Но все ухудшается. Мьютексы и условия, которые используют внутреннее использование: interprocess, сохраняются в начале сегмента. Поэтому, если вы случайно напишите в some_null_offset_ptr- > some_member, вы начнете перезаписывать внутреннюю машину сегмента boost:: interprocess и получить совершенно странное и труднопонятное поведение. Написание кода, который координирует несколько процессов и имеет дело с возможными условиями гонки, может быть жестким само по себе, поэтому он был вдвойне сумасшедшим.

В итоге я написал свою собственную минимальную библиотеку разделяемой памяти и использовал системный вызов POSIX mprotect, чтобы сделать первую страницу моих разделяемых сегментов памяти нечитаемой и невоспроизводящейся, что сразу же вызвало ошибки NULL (вы теряете страницу памяти, но такую маленькая жертва стоит того, если вы не на встроенной системе). Вы можете попробовать использовать boost:: interprocess, но все же вручную вызывать mprotect, но это не сработает, потому что boost ожидает, что он сможет записать эту внутреннюю информацию, хранящуюся в начале сегмента.

Наконец, offset_ptr предположим, что вы храните указатели в сегменте общей памяти в других точках одного и того же сегмента разделяемой памяти. Если вы знаете, что у вас будет несколько разделов разделяемой памяти (я знал, что это будет так, потому что для меня, потому что у меня был один записываемый сегмент и 1 только для чтения сегмент), который будет хранить указатели друг в друга, offset_ptr будет мешать вы должны сделать кучу ручных преобразований. В моей библиотеке разделяемой памяти я создал шаблонный SegmentPtr<i> класс, где SegmentPtr<0> был бы указателем на один сегмент, SegmentPtr<1> был бы указателем на другой сегмент и т.д., Чтобы их нельзя было перепутать (вы можете сделать это только хотя, если вы знаете количество сегментов во время компиляции).

Вам нужно взвесить стоимость реализации всего, что вам нужно, и дополнительное время отладки, которое вы собираетесь потратить на отслеживание ошибок NULL и, возможно, смешение указателей на разные сегменты (последнее не обязательно для вас). Для меня это стоило того, что я сам реализовал, но я не сильно использовал структуры данных boost:: interprocess, поэтому это было явно стоит. Если библиотеке разрешено быть открытым исходным кодом в будущем (не до меня), я обновляю ссылку, но пока не задерживаю дыхание, p

Что касается вашего коллеги: я не испытывал никакой нестабильности или ошибок в boost:: interprocess. Я просто думаю, что его дизайн затрудняет поиск ошибок в вашем собственном коде.

Ответ 2

Мы используем совместную память boost:: interprocess и interprocess.synchronization_mechanisms.message_queue в течение примерно 6 месяцев и нашли код надежным, стабильной и довольно простой в использовании.

Мы сохраняем наши данные в довольно простой структуре фиксированного размера (хотя 12 регионов с общим размером 2 + gb), и мы использовали код примера boost: interprocess как есть и почти не имели проблем.

Мы обнаружили два элемента, которые нужно учитывать при использовании boost:: interprocess с окнами.

  • Обзор Увеличьте общую память и Windows. Если вы используете объекты по умолчанию #include <boost/interprocess/shared_memory_object.hpp>, то вы можете увеличить размер области с отображением памяти, только сначала перезагрузив Windows. Это связано с тем, что boost использует хранилище резервных копий файлов.
  • Класс message_queue использует файл shared_memory_object по умолчанию. Поэтому, если размер сообщения необходимо увеличить, перезагрузите время Windows снова.

Я не пытаюсь сказать, что сообщение Джозефа Гарвина о его проблемах с boost:: interprocess недействительно. Я думаю, что различия в нашем опыте связаны с использованием различных аспектов библиотеки. Я согласен с ним в том, что в boost:: interprocess нет проблем с стабильностью.