mmap(): что произойдет, если базовый файл изменится (сожмется)?

Если вы сопоставляете файл с памятью, используя mmap(), но тогда основной файл изменяется на гораздо меньший размер. Что произойдет, если вы получите доступ к смещению памяти, которое было выбрито из файла?


person zer0stimulus    schedule 29.07.2011    source источник


Ответы (3)


IBM говорит, что это неопределенный http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Fapis%2Fmmap.htm

Если размер отображаемого файла уменьшается после mmap(), попытки ссылки за пределы файла не определены и могут привести к исключению MCH0601.

Если размер файла увеличивается после завершения функции mmap(), то целые страницы за исходным концом файла не будут доступны через сопоставление.

То же самое сказано в спецификации SingleUnix: http://pubs.opengroup.org/onlinepubs/7908799/xsh/mmap.html

Если размер сопоставленного файла изменяется после вызова mmap() в результате какой-либо другой операции с сопоставленным файлом, влияние ссылок на части сопоставленной области, которые соответствуют добавленным или удаленным частям файла не указано.

«не определено» или «не указано» означает, что ОС разрешено начинать форматирование диска или что-то еще. Скорее всего, SIGSEGV убивает ваше приложение.

person osgx    schedule 29.07.2011
comment
Я бы сказал, что это один из случаев, когда UB может столкнуться с ошибками ОС, вызывающими потерю данных: lwn.net/ Статьи/357767 - person ninjalj; 29.07.2011
comment
@osgx В Linux это SIGBUS. - person Matthew Hall; 23.11.2012

Это зависит от того, какие флаги вы указали на mmap странице руководства:

MAP_SHARED Поделитесь этим сопоставлением. Обновления отображения видны другим процессам, которые отображают этот файл, и переносятся в базовый файл. Файл может не обновляться до тех пор, пока не будет вызвана msync(2) или munmap().

а также

MAP_PRIVATE Создать частное сопоставление копирования при записи. Обновления сопоставления невидимы для других процессов, отображающих тот же файл, и не переносятся в базовый файл. Не указано, видны ли изменения, сделанные в файле после вызова mmap(), в отображаемой области.

Так что для MAP_PRIVATE не имеет значения, у каждого автора фактически есть «частная» копия. (хотя это только копии, когда происходит операция мутирования).

Я думаю, что если вы используете MAP_SHARED, то ни один другой процесс не сможет открыть файл с привилегиями записи. Но это предположение.

РЕДАКТИРОВАНИЕ: ninjalj прав, файл можно изменить, даже если вы mmap с MAP_SHARED.

person Evan Teran    schedule 29.07.2011
comment
почему ты так думаешь? В конце концов, отображаемый файл — это не что иное, как разделяемая память с файловой поддержкой. Если вам нужна защита, используйте семафоры/мьютексы на уровне процесса или какой-нибудь алгоритм без блокировки. - person ninjalj; 29.07.2011
comment
@ninjalj: Похоже, ты прав. Я думал о проблеме чтения/записи (максимум 1 писатель или 1+ читателей, но никогда оба). По-видимому, раньше был флаг для получения поведения, о котором я думал, но он был удален, так как его можно было использовать в локальной DoS-атаке. - person Evan Teran; 29.07.2011

Согласно справочным страницам, mmap возвращает ошибку EINVAL, когда вы пытаетесь получить доступ к адресу, который слишком велик для текущего сопоставления файлов.

«dnotify» и «inotify» — это текущие службы уведомлений об изменении файлов в ядре Linux. Предположительно, они будут информировать подсистему mmap об изменениях в файле.

person Gearoid Murphy    schedule 29.07.2011
comment
Что делать, если файл укорачивается после возврата mmap? Не будет никаких шансов получить ошибку при вызове mmap. - person osgx; 29.07.2011
comment
Я только что попробовал это, используя stat для расчета размера файла, я сделал файл mmap, распечатал все содержимое, подождал 5 секунд (пока я удалил несколько строк) и снова распечатал все содержимое, используя переменную stat ( без изменений по сравнению с моим первоначальным вызовом статистики), он работал нормально и распечатывал контрактное содержимое. - person Gearoid Murphy; 29.07.2011
comment
Gearoid Murphy, это очень ненадежно, потому что это зависит от использования дискового кеша Linux (кеша страниц) и от типа отображения. - person osgx; 29.07.2011