Короткий (и неудовлетворительный ответ): вы не можете заставить shm_open
потерпеть неудачу, если на /dev/shm
недостаточно места.(Вы можете принудительно заставить его завершиться с ошибкой, явно установив предел размера файла процесса, используя setrlimit
, чтобы изменить RLIMIT_FSIZE
, но это глобальный параметр, неприменимый к отдельной файловой системе, так что это почти наверняка не то, что вы хотите.)
Когда Posix стандартизировал разделяемую память, были рассмотрены различные варианты реализации и была предпринята попытка обеспечить значительную гибкость реализации, если это не усложняет интерфейс.В частности, во многих реализациях Unix уже есть механизмы для сопоставления файловых объектов непосредственно с памятью процесса, а для файловых систем на основе памяти - комбинация, идеально подходящая для реализации разделяемой памяти:
Простая разделяемая память явноособый случай более общей возможности сопоставления файлов.Кроме того, существует довольно распространенное соглашение и реализация интерфейса сопоставления файлов.В этих системах много разных типов объектов могут отображаться (например, файлы, память, устройства и т. Д.) С использованием одних и тех же интерфейсов сопоставления.Такой подход минимизирует распространение интерфейса и максимизирует универсальность программ, использующих интерфейсы отображения. (из Обоснование Posix: функции сопоставленного файла )
В частности, «… вышеприведенные требования не исключают: [t] объект разделяемой памяти изреализуется с использованием реальных файлов в реальной файловой системе. " ( Обоснование Posix: объекты общей памяти ) .Хотя я не верю, что библиотека Linux делает это, Posix даже позволяет реализовывать shm_open()
как макрос, заключающий в себе обычный вызов open()
;в случае реализаций (таких как Linux), которые просто отображают общую память в файловую систему, ничто не требует специальной обработки системного интерфейса ftruncate()
.
Важно выделить один аспектftruncate()
вызов (выделение добавлено):
Если размер файла увеличивается, расширенная область должна выглядеть так, как если бы была заполнена нулями.
Многие файловые системы допускают "разреженные файлы".В разреженном файле файловые блоки, полностью заполненные нулями, просто не отображаются на физическое хранилище;если приложение читает один из этих блоков, оно получает страницу с нулями.Если блок модифицируется и фиксируется на диске, то и только тогда файловая система выделяет хранилище для блока.[Примечание 1]
Ленивое выделение заполненных нулями блоков означает, что в случае, когда ftruncate()
расширяет файл, ему нужно только обновить метаданные файла, что позволяет ему очень быстро возвращаться.Если требуемый размер не превышает ограничение размера файла процесса (или ограничение файловой системы в случае файловых систем, которые не используют достаточно большие целочисленные типы для размеров файлов), ошибка ftruncate()
не будет выдана.Ошибка возникает, когда становится невозможно выделить физическое хранилище (или выделенный буфер памяти, в случае файла с отображением в памяти).
Это полностью соответствует оптимистическому подходу Linux к распределению памяти: mmap
всегда завершается успешно (пока доступно адресное пространство), а ошибка отмечается только при фактическом использовании памяти.(Но этот конкретный подход к реализации совместно используемой памяти не ограничивается теми, которые используют оптимистичное распределение памяти.)
Примечания
- Я использовал это для демонстрации, сохраняя файл 2 ГБ вдискета, но я полагаю, что многие читатели сегодня даже не будут знать, что такое дискета, тем более, какова была ее фактическая емкость.