Общая память, созданная в очереди сообщений Boost, слишком мала? - PullRequest
0 голосов
/ 29 ноября 2018

Я создаю приложение, в котором несколько процессов обмениваются данными через очереди повышенных сообщений.Очереди создаются с помощью конструктора очередей сообщений как message_queue(open_or_create, name, max_num_msg, max_msg_size); Я использую open_or_create для всех очередей во всех процессах, поскольку не указан порядок, в котором должны создаваться очереди.max_num_msg = 200 и max_msg_size = 500000.

Теперь с созданием все в порядке, но после отправки сообщений через очереди некоторое время возникают внезапные сбои из-за нарушений прав чтения.Небольшая отладка привела меня к определению do_send в message_queue.hpp, где для написания сообщения получен пустой заголовок сообщения

  //Insert the first free message in the priority queue
  ipcdetail::msg_hdr_t<VoidPointer> &free_msg_hdr = p_hdr->queue_free_msg(priority);

  //Sanity check, free msgs are always cleaned when received
  BOOST_ASSERT(free_msg_hdr.priority == 0);
  BOOST_ASSERT(free_msg_hdr.len == 0);

Ошибка происходит в free_msg_hdr.priority == 0, поскольку адресfree_msg_hdr не указывает на читаемое местоположение.

Проведение еще нескольких исследований показало, что при создании очереди

template<class VoidPointer>
inline message_queue_t<VoidPointer>::message_queue_t(open_or_create_t,
    const char *name,
    size_type max_num_msg,
    size_type max_msg_size,
    const permissions &perm)
    //Create shared memory and execute functor atomically
    : m_shmem(open_or_create,
        name,
        get_mem_size(max_msg_size, max_num_msg),
        read_write,
        static_cast<void*>(0),
        //Prepare initialization functor
        ipcdetail::msg_queue_initialization_func_t<VoidPointer>(max_num_msg, max_msg_size),
        perm)
{}

созданный объект общей памяти m_shmem имеетразмер слишком мал, чтобы вместить 200 сообщений размером 500000. Это объясняет, почему сбои немного непредсказуемы, поскольку все еще меньшая часть памяти доступна, поэтому для случайного попадания в недоступные части требуется некоторое время.Тем не менее, я до сих пор не знаю, почему это происходит.Глядя на функцию get_mem_size(max_msg_size, max_num_msg), она возвращает правильный размер, но затем после создания размер становится меньше.Если я затем воссоздаю ту же очередь, она обычно получает правильный размер, и я никогда не получаю никаких исключений.Если у кого-то есть представление о том, почему это может происходить, или предложения о дальнейшей отладке этой проблемы, это будет высоко оценено.

Я, вероятно, должен упомянуть, что приложение скомпилировано в Visual C ++ в 32 бита иработает в Windows 10. Может ли реализация общей памяти Windows вызывать такую ​​проблему?

1 Ответ

0 голосов
/ 13 декабря 2018

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

В нашем случае было относительно легко убедиться, что другие процессы открывают очередь только после того, как мы уверены, что она создана, и, следовательно, наша проблема решена!

...