У меня есть приложение на С++, которое распределяет общую память в системе Linux через shmget (2). Данные, хранящиеся в общей памяти, периодически растут, и я хотел бы изменить размер разделяемой памяти таким образом, чтобы realloc() увеличивал регулярную память. Есть ли способ сделать это? Я нашел документ на веб-сайте IBM, в котором упоминается команда SHM_SIZE, но в файлах Linux и BSD этого нет, даже в разделах, относящихся к Linux.
Могу ли я изменить размер разделяемой памяти Linux на shmctl?
Ответ 1
Простой ответ: нет простого способа.
Причины довольно логичны. Общая память привязывается к виртуальному пространству каждого процесса индивидуально. Каждый процесс имеет собственное виртуальное адресное пространство. Каждый процесс может свободно привязывать сегмент к любому (не буквально, выравниванию устанавливает некоторые ограничения) произвольный адрес. Как система может гарантировать, что, скажем, путем расширения области на 4MiB, каждый "пользователь" этого сегмента сможет соответствовать блоку "большой" в том же стартовом адресе, где ранее был меньший сегмент?
Но вы не должны сдаваться! Вы можете быть творческими. Вы можете придумать один сегмент заголовка, в котором вы храните информацию о реальном сегменте полезной нагрузки. Вы можете сделать каждый процесс подчиненным некоторым правилам, например: повторно подключить сегмент полезной нагрузки, когда его идентификатор, как описано в сегменте заголовка, не соответствует известному.
Совет: я подозреваю, что вы это знаете, но никогда не держите указатели на данные в общей области, только смещение.
Надеюсь, у вас будет какая-то польза от моей тарабарщины.
Ответ 2
Мне кажется, что вы можете написать свой собственный менеджер памяти для своей цели. Концепция довольно проста:
- У вас есть общий блок памяти, размер которого
N
bytes; - Выделить новый блок разделяемой памяти с размером
2*N
; - Копирование памяти из одного блока в другой;
- Свободный старый блок разделяемой памяти;
- Оберните # 2-4 в какую-то рутину и используйте ее;
Я боюсь, что мы не имеем ничего общего с этим. Вот как реализуется std::vector
. И void *realloc()
в большинстве случаев вернет вам указатель на новый блок памяти (но не на расширенный старый блок).