SIGBUS на Mmap с MAP_FIXED | MAP_FILE | MAP_SHARED

:) Я пытаюсь перенести какой-то устаревший код (большую программу) на CentOS 7, но я попадаюсь в ловушку. Суть кода - довольно странная структура, построенная вокруг использования mmap для выделения жестко запрограммированного адреса и сопоставления файла с ним. Файл действует как база данных (и создается на основе одного) и содержит жестко закодированные указатели на различные разделы отображаемой памяти. Очень некрасиво, но это то, что есть. Вся программа построена вокруг этой структуры, и никто не собирается финансировать переписывание.

Проблема возникает в строке mmap. Это работало раньше, но больше не на CentOS 7:

mmapAddr = mmap ((void *) SMAddr, SMA_WINDOW_SIZE, PROT_READ | (readOnly ? 0 : PROT_WRITE),MAP_FILE | MAP_FIXED | MAP_SHARED, SMFileDesc, 0);

... где SMAddr является 0x8000000, SMA_WINDOW_SIZE является 127926272, а также readOnly ложно Так что в основном он пытается сопоставить файл с адресом 0x8000000 с размером 122MB.

Что могло измениться между версиями, я понятия не имею. Но я отмечаю, что отображаемый файл занимает всего 1,5 МБ. Я не совсем уверен, почему он должен отображать намного больше, чем размер файла, но я знаю, что это необходимо, и я знаю, что по каким-то причинам было выбрано много "нюансов" при выборе размера "122 МБ".

Могло ли быть несоответствие между фактическим размером файла и выделенным размером в прошлом, но не больше? я знаю это SIGBUS означает попытку доступа к неверной области памяти. Учитывая, что mmap не принимает какой-либо выделенный указатель, это должно быть то, что он делает внутри.

Я пробовал ловить и блокировать SIGBUS (думая, что, может быть, это будет игнорируемо?), но программа все еще зависала с SIGBUS на том же месте. Возможно я сделал это неправильно.

Мысли?

1 ответ

Отсюда 1:

Функцию mmap() можно использовать для отображения области памяти, которая больше текущего размера объекта. Доступ к памяти в пределах отображения, но за пределами текущего конца базовых объектов может привести к тому, что сигналы SIGBUS будут отправлены процессу. Причина этого заключается в том, что размер объекта может изменяться другими процессами и может изменяться в любой момент. Реализация должна сообщить приложению, что ссылка на память находится вне объекта, где это может быть обнаружено; в противном случае записанные данные могут быть потеряны, а прочитанные данные могут не отражать фактические данные в объекте.

Обратите внимание, что ссылки за концом объекта не расширяют объект, поскольку новый конец не может быть точно определен большинством оборудования виртуальной памяти. Вместо этого можно напрямую управлять размером с помощью функции ftruncate().

Поэтому, скорее всего, ошибка в том, что ваша программа пытается получить доступ к области отображенной памяти, которая находится вне файла. Однако вызов mmap должен быть успешным. Какое возвращаемое значение вы получаете?

Другие вопросы по тегам