ИМЯ
shmget -
    выделяет
    общий
    сегмент
    памяти System V
ОБЗОР
#include <sys/ipc.h>
  
  #include <sys/shm.h>
int shmget(key_t key, size_t size,
    int shmflg);
ОПИСАНИЕ
Вызов shmget()
    возвращает
    идентификатор
    общего
    сегмента
    памяти System V,
    соответствующего
    значению
    аргумента
    key. Его
    можно
    использовать
    для
    получения
    идентификатора
    ранее
    созданного
    общего
    сегмента
    памяти
    (когда shmflg
    равно нулю
    и key не
    содержит
    значения
    IPC_PRIVATE) или для
    создания
    нового.
Новый
    общий
    сегмент
    памяти
    размером
    size,
    округлённым
    до
    значения,
    кратного
    PAGE_SIZE
    создаётся,
    если
    значение key
    равно IPC_PRIVATE
    или, если key
    не равно
    IPC_PRIVATE, но не
    существует
    общего
    сегмента
    памяти,
    который бы
    соответствовал
    значению key
    и в shmflg есть
    флаг IPC_CREAT.
Если в shmflg
    одновременно
    указаны IPC_CREAT
    и IPC_EXCL и для
    значения key
    уже
    существует
    общий
    сегмент
    памяти, то
    вызов shmget()
    завершается
    с ошибкой и
    errno
    присваивается
    EEXIST (такой же
    результат
    как с O_CREAT | O_EXCL у
    open(2)).
Значение
    shmflg
    составляется
    из
    следующих
    флагов:
  - IPC_CREAT
- Служит для
      создания
      нового
      сегмента.
      Если этого
      флага нет,
      то вызов shmget()
      будет
      искать
      сегмент,
      соответствующий
      key, и затем
      проверит,
      имеет ли
      пользователь
      права на
      доступ к
      сегменту.
- IPC_EXCL
- Этот флаг
      используется
      совместно
      с IPC_CREAT для
      того, чтобы
      этот вызов
      создал
      сегмент.
      Если
      сегмент
      уже
      существует,
      то вызов
      завершается
      с ошибкой.
- SHM_HUGETLB
    (начиная с Linux
    2.6)
- Выделять
      сегмент
      используя
      «огромные
      страницы».
      Дополнительную
      информацию
      смотрите в
      файле
      исходного
      кода ядра Linux
      Documentation/admin-guide/mm/hugetlbpage.rst.
- SHM_HUGE_2MB,
    SHM_HUGE_1GB
    (начиная с Linux
    3.8)
- Используется
      вместе с
      SHM_HUGETLB для
      выбора
      других
      размеров
      страниц hugetlb
      (2 МБ и 1 МБ,
      соответственно)
      в системах,
      которые
      поддерживают
      несколько
      размеров
      страниц hugetlb.
  
  - Вообще,
      желаемые
      размер
      огромной
      страницы
      можно
      настроить
      закодировав
      логарифмом
      по
      основанию 2
      желаемый
      размер
      страницы в
      шести
      битах
      смещения
      SHM_HUGE_SHIFT. Таким
      образом,
      приведённые
      выше
      константы
      определяются
      так:
- 
    
    #define SHM_HUGE_2MB    (21 << SHM_HUGE_SHIFT)
#define SHM_HUGE_1GB    (30 << SHM_HUGE_SHIFT)
 
- Дополнительную
      информацию
      о схожих по
      имени
      константах
      смотрите в
      mmap(2).
  - SHM_NORESERVE
    (начиная с Linux
    2.6.15)
- Этот флаг
      нужен для
      того же,
      что и флаг
      MAP_NORESERVE у mmap(2). Он
      указывает
      не
      резервировать
      место в
      пространстве
      подкачки
      для этого
      сегмента.
      Операцией
      резервирования
      места в
      пространстве
      подкачки
      гарантируется,
      что
      сегмент
      можно
      изменить.
      Если место
      не
      резервировать,
      то при
      записи
      можно
      получить
      сигнал SIGSEGV,
      если
      кончится
      физическая
      память.
      Смотрите
      также
      обсуждение
      файла
      /proc/sys/vm/overcommit_memory в proc(5).
В
    дополнении
    к
    перечисленным
    выше
    флагам в
    младших 9
    битах shmflg
    задаются
    права для
    владельца,
    группы и
    всех
    остальных.
    Формат
    значения
    битов
    совпадает
    с
    аргументом
    mode вызова open(2).
    В данный
    момент бит
    выполнения
    системой
    не
    используются.
Если
    создаётся
    новый
    общий
    сегмент
    памяти, то
    его
    содержимое
    инициализируется
    нулями, а
    соответствующая
    ему
    структура
    данных 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
      присваивается
      значение
      текущего
      времени.
Если
    общий
    сегмент
    памяти уже
    существует,
    то
    проверяются
    права
    доступа к
    нему и не
    помечен ли
    он для
    удаления.
ВОЗВРАЩАЕМОЕ
  ЗНАЧЕНИЕ
При
    успешном
    выполнении
    возвращается
    корректный
    идентификатор
    общей
    памяти. При
    ошибке
    возвращается
    -1, а в errno
    записывается
    причина
    ошибки.
ОШИБКИ
В случае
    возникновения
    ошибки errno
    может
    принимать
    следующие
    значения:
  - EACCES
- Пользователь
      не имеет
      прав
      доступа к
      общему
      сегменту
      памяти и не
      имеет
      мандата
      CAP_IPC_OWNER в
      пространстве
      имён
      пользователя,
      который
      управляет
      его
      пространством
      имён IPC.
- EEXIST
- В shmflg
      указаны IPC_CREAT
      и IPC_EXCL, но
      общий
      сегмент
      памяти уже
      существует
      для key.
- EINVAL
- Был создан
      новый
      сегмент и
      size меньше SHMMIN
      или больше
      SHMMAX.
- EINVAL
- Сегмент
      для
      заданного
      key
      существует,
      но size
      больше
      размера
      этого
      сегмента.
- ENFILE
- Достигнуто
      максимальное
      количество
      открытых
      файлов в
      системе.
- ENOENT
- Не
      существует
      сегмента
      для ключа
      key и флаг IPC_CREAT
      не указан.
- ENOMEM
- Не хватает
      памяти для
      выделения
      под
      перерасход
      сегмента.
- ENOSPC
- Все
      возможные
      идентификаторы
      сегментов
      уже
      распределены
      (SHMMNI) или
      размер
      выделяемого
      сегмента
      превысит
      системные
      лимиты по
      общей
      памяти (SHMALL).
- EPERM
- Указан
      флаг SHM_HUGETLB, но
      у
      вызывающего
      нет прав
      (нет
      мандата
      CAP_IPC_LOCK).
СООТВЕТСТВИЕ
  СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008, SVr4.
SHM_HUGETLB и SHM_NORESERVE
    являются
    расширениями
    Linux.
ЗАМЕЧАНИЯ
Включение
    файлов <sys/types.h>
    и <sys/ipc.h> не
    требуется
    в Linux или
    любых
    версий POSIX.
    Однако,
    некоторые
    старые
    реализации
    требуют
    включения
    данных
    заголовочных
    файлов, и
    это также
    требуется
    по SVID. В
    приложениях,
    которые
    нужно
    перенести
    на такие
    старые
    системы,
    может
    потребоваться
    включить
    данных
    заголовочные
    файлы.
IPC_PRIVATE — не
    поле флага,
    а тип key_t.
    Если key
    равно
    этому
    специальному
    значению,
    то
    системный
    вызов
    игнорирует
    всё кроме
    9-ти младших
    битов shmflg и
    создаёт
    новый
    общий
    сегмент
    памяти.
Ограничения
  общей
  памяти
Ниже
    приведены
    ограничения
    ресурсов
    на общий
    сегмент
    памяти,
    влияющие
    на вызов
  shmget():
  - SHMALL
- Системный
      лимит на
      полный
      объём
      общей
      памяти,
      измеряется
      в единицах,
      равных
      размеру
      системной
      страницы.
  
  - В Linux это
      ограничение
      можно
      прочитать
      и изменить
      через /proc/sys/kernel/shmmni.
      Начиная с 3.16,
      значение
      по
      умолчанию
      равно:
- 
    
     ULONG_MAX - 2^24
- Эффект
      этого
      значения
      (которое
      подходит и
      для
      32-разрядной,
      и для
      64-разрядной
      системы) —
      не задать
      ограничение
      на
      выделения.
      Это
      значение, в
      отличии от
      ULONG_MAX, было
      выбрано в
      качестве
      значения
      по
      умолчанию,
      чтобы
      предотвратить
      некоторые
      случаи,
      когда
      старые
      приложения
      просто
      увеличивают
      существующий
      предел без
      начальной
      проверки
      его
      текущего
      значения.
      Такие
      приложения
      переполнили
      бы
      значение,
      если
      предел был
      равен ULONG_MAX.
- В Linux 2.4 по Linux 3.15
      значение
      по
      умолчанию
      этого
      ограничения
      было:
- 
    
     SHMMAX / PAGE_SIZE * (SHMMNI / 16)
- Если SHMMAX и SHMMNI
      не
      изменены,
      то
      умножение
      результата
      этой
      формулы на
      размер
      страницы
      (для
      получения
      значения в
      байтах)
      даёт
      значение
      8 ГБ —
      ограничение
      на общее
      количество
      памяти,
      используемой
      во всех
      общих
      сегментах
      памяти.
  - SHMMAX
- Максимальный
      размер
      общего
      сегмента
      памяти в
      байтах.
  
  - В Linux это
      ограничение
      можно
      прочитать
      и изменить
      через /proc/sys/kernel/shmmax.
      Начиная с 3.16,
      значение
      по
      умолчанию
      равно:
- 
    
     ULONG_MAX - 2^24
- Эффект
      этого
      значения
      (которое
      подходит и
      для
      32-разрядной,
      и для
      64-разрядной
      системы) —
      не задать
      ограничение
      на
      выделения.
      Смотрите
      описание
      SHMALL о том,
      почему
      используется
      именно
      такое
      значение
      по
      умолчанию
      (а не ULONG_MAX).
- В Linux 2.2 по Linux 3.15
      значение
      по
      умолчанию
      этого
      ограничения
      равно 0x2000000
      (32 МБ).
- Так как
      невозможно
      отобразить
      только
      часть
      общего
      сегмента
      памяти,
      размер
      виртуальной
      памяти
      отличается
      от
      ограничения
      на
      максимальный
      размер
      подходящего
      сегмента:
      например,
      на i386 самые
      большие
      сегменты,
      которые
      можно
      отображать,
      имеют
      размер
      около 2.8 ГБ,
      а на x86-64 —
      около 127 ТБ.
  - SHMMIN
- Минимальный
      размер
      общего
      сегмента
      памяти в
      байтах в
      системе:
      зависит от
      реализации
      (в
      настоящий
      момент
      равно 1
      байту, хотя
      на самом
      деле
      минимальный
      выделяемый
      размер
      равен PAGE_SIZE).
- SHMMNI
- Системный
      лимит на
      общее
      количество
      общих
      сегментов
      памяти.
      Начиная с Linux
      2.2, значение
      по
      умолчанию
      равно 128;
      начиная с Linux
      2.4, значение
      по
      умолчанию
      равно 4096.
  
  - В Linux это
      ограничение
      можно
      прочитать
      и изменить
      через
    /proc/sys/kernel/shmmni.
Реализацией
    не
    ограничивается
    максимальное
    количество
    общих
    сегментов
    памяти на
    процесс
  (SHMSEG).
Замечания,
  касающиеся
  Linux
В Linux до
    версии 2.3.30
    вызов shmget()
    возвращал
    значение
    EIDRM, если
    общий
    сегмент
    памяти был
    запланирован
    к
  удалению.
ДЕФЕКТЫ
Имя IPC_PRIVATE,
    возможно,
    было
    выбрано
    неудачно,
    IPC_NEW
    отражает
    смысл
    действия
    более
  ясно.