Могу ли я изменить размер разделяемой памяти Linux на shmctl?

У меня есть приложение на С++, которое распределяет общую память в системе Linux через shmget (2). Данные, хранящиеся в общей памяти, периодически растут, и я хотел бы изменить размер разделяемой памяти таким образом, чтобы realloc() увеличивал регулярную память. Есть ли способ сделать это? Я нашел документ на веб-сайте IBM, в котором упоминается команда SHM_SIZE, но в файлах Linux и BSD этого нет, даже в разделах, относящихся к Linux.

Ответ 1

Простой ответ: нет простого способа.

Причины довольно логичны. Общая память привязывается к виртуальному пространству каждого процесса индивидуально. Каждый процесс имеет собственное виртуальное адресное пространство. Каждый процесс может свободно привязывать сегмент к любому (не буквально, выравниванию устанавливает некоторые ограничения) произвольный адрес. Как система может гарантировать, что, скажем, путем расширения области на 4MiB, каждый "пользователь" этого сегмента сможет соответствовать блоку "большой" в том же стартовом адресе, где ранее был меньший сегмент?

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

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

Надеюсь, у вас будет какая-то польза от моей тарабарщины.

Ответ 2

Мне кажется, что вы можете написать свой собственный менеджер памяти для своей цели. Концепция довольно проста:

  • У вас есть общий блок памяти, размер которого N bytes;
  • Выделить новый блок разделяемой памяти с размером 2*N;
  • Копирование памяти из одного блока в другой;
  • Свободный старый блок разделяемой памяти;
  • Оберните # 2-4 в какую-то рутину и используйте ее;

Я боюсь, что мы не имеем ничего общего с этим. Вот как реализуется std::vector. И void *realloc() в большинстве случаев вернет вам указатель на новый блок памяти (но не на расширенный старый блок).