SHMGET(2)

ИМЯ
shmget - выделяет общий сегмент памяти

ОБЗОР
#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

ОПИСАНИЕ
Вызов shmget() возвращает идентификатор общего сегмента памяти, соответствующего значению аргумента key. Если значение key равно IPC_PRIVATE или если key не равно IPC_PRIVATE, но не существует общего сегмента памяти, который бы соответствовал значению key и в shmflg есть флаг IPC_CREAT, то создаётся новый общий сегмент памяти размером size, округлённым до значения, кратного PAGE_SIZE.

Если в shmflg одновременно указаны IPC_CREAT и IPC_EXCL и для значения key уже существует общий сегмент памяти, то вызов shmget() завершается с ошибкой и errno присваивается EEXIST (такой же результат как с O_CREAT | O_EXCL у open(2)).

Значение shmflg составляется из следующих флагов:

IPC_CREAT
    Служит для создания нового сегмента. Если этого флага нет, то вызов shmget() будет искать сегмент, соответствующий key, и затем проверит, имеет ли пользователь права на доступ к сегменту.

IPC_EXCL
    Используется совместно с IPC_CREAT для того, чтобы отказаться от создания при наличии сегмента.

mode_flags
    В младших 9 битах задаются права для владельца, группы и всех остальных. Формат значения совпадает с аргументом mode вызова open(2). В данный момент бит выполнения системой не используются.

SHM_HUGETLB (начиная с Linux 2.6)
    Выделять сегмент используя «огромные страницы». Дополнительную информацию смотрите в файле исходного кода ядра Documentation/vm/hugetlbpage.txt.

SHM_NORESERVE (начиная с Linux 2.6.15)
    Этот флаг нужен для того же, что и флаг MAP_NORESERVE у mmap(2). Он указывает не резервировать место в пространстве подкачки для этого сегмента. Операцией резервирования места в пространстве подкачки гарантируется, что сегмент можно изменить. Если место не резервировать, то при записи можно получить сигнал SIGSEGV, если кончится физическая память. Смотрите также обсуждение файла /proc/sys/vm/overcommit_memory в proc(5).

Если создаётся новый общий сегмент памяти, то его содержимое инициализируется нулями, а соответствующая ему структура данных shmid_ds (см. shmctl(2)) следующим образом:

    Полям shm_perm.cuid и shm_perm.uid присваиваются значения эффективного идентификатора пользователя вызывающего процесса.

    Полям shm_perm.cgid и shm_perm.gid присваиваются значения эффективного идентификатора группы вызывающего процесса.

    Младшим 9 битам shm_perm.mode присваивается значение младших 9 бит shmflg.

    Полю shm_segsz присваивается значение size.

    Полям shm_lpid, shm_nattch, shm_atime и shm_dtime присваивается 0.

    Полю shm_ctime присваивается значение текущего времени.

Если общий сегмент памяти уже существует, то проверяются права доступа к нему и не помечен ли он для удаления.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении возвращается корректный идентификатор сегмента shmid и -1 в случае ошибки.

ОШИБКИ
В случае возникновения ошибки errno может принимать следующие значения:

EACCES
    Пользователь не имеет прав доступа к общему сегменту памяти и не имеет мандата CAP_IPC_OWNER.

EEXIST
    Указан флаг IPC_CREAT | IPC_EXCL и сегмент существует.

EINVAL
    Был создан новый сегмент и size < SHMMIN или size > SHMMAX, или новый сегмент не создан, т.к. существует сегмент с указанным ключом, но size больше размера этого сегмента.

ENFILE
    Достигнуто максимальное количество открытых файлов в системе.

ENOENT
    Не существует сегмента для ключа key и флаг IPC_CREAT не указан.

ENOMEM
    Не хватает памяти для выделения под перерасход сегмента.

ENOSPC
    Все возможные идентификаторы сегментов уже распределены (SHMMNI) или размер выделяемого сегмента превысит системные лимиты по общей памяти (SHMALL).

EPERM
    Указан флаг SHM_HUGETLB, но у вызывающего нет прав (нет мандата CAP_IPC_LOCK).

СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, POSIX.1-2001. Флаг SHM_HUGETLB является непереносимым расширением Linux.

ЗАМЕЧАНИЯ
Включение файлов <sys/types.h> и <sys/ipc.h> не требуется в Linux или любых версий POSIX. Однако, некоторые старые реализации требуют включения данных заголовочных файлов, и это также требуется по SVID. В приложениях, которые нужно перенести на такие старые системы, может потребоваться включить данных заголовочные файлы. IPC_PRIVATE не поле флага, а тип key_t. Если key равно этому значению, то системный вызов игнорирует всё кроме 9-ти младших битов shmflg и создаёт новый общий сегмента памяти (при успешном выполнении).

Ниже приведены лимиты ресурсов на общий сегмент памяти, влияющие на вызов shmget():

SHMALL
    Максимальное количество страниц общей памяти в системе (в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmall).

SHMMAX
    Максимальный размер общего сегмента памяти в байтах в системе: зависит от политики (в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmmax).

SHMMIN
    Минимальный размер общего сегмента памяти в байтах в системе: зависит от реализации (в настоящий момент равно 1 байту, хотя на самом деле минимальный выделяемый размер равен PAGE_SIZE).

SHMMNI
    Максимальное количество сегментов общей памяти в системе: зависит от реализации (в настоящий момент — 4096, до Linux 2.3.99 было равно 128; в Linux это ограничение можно получить и изменить через /proc/sys/kernel/shmmni).

Реализацией не ограничивается максимальное количество общих сегментов памяти на процесс (SHMSEG).

  Замечания, касающиеся Linux
В Linux до версии 2.3.30 вызов shmget() возвращал значение EIDRM, если общий сегмент памяти был запланирован к удалению.

ДЕФЕКТЫ
Имя IPC_PRIVATE, возможно, было выбрано неудачно, IPC_NEW отражает смысл действия более ясно.

СМОТРИТЕ ТАКЖЕ
shmat(2), shmctl(2), shmdt(2), ftok(3), capabilities(7), shm_overview(7), svipc(7)