shmget()
возвращает идентификатор разделяемому сегменту памяти,
соответствующий значению аргумента
key.
Создается новый разделяемый сегмент памяти с размером
size(
округленным до размера, кратного
PAGE_SIZE),
если значение
key
равно
IPC_PRIVATE
или если значение
key
не равно
IPC_PRIVATE
и нет идентификатора, соответствующего
key;
причем, выражение
shmflg&IPC_CREAT
истинно.
Поле
shmflg
состоит из:
IPC_CREAT
служит для создания нового сегмента. Если этого флага нет, то функция
shmget()
будет искать сегмент, соответствующий ключу key и затем проверит,
имеет ли пользователь права на доступ к сегменту.
IPC_EXCL
используется совместно с IPC_CREAT для того, чтобы не создавать
существующий сегмент заново.
mode_flags (младшие 9 битов)
указывают на права хозяина, группы и др.
В данный момент права системой не используются.
Если создается новый сегмент, то права доступа копируются из
shmflg
в
shm_perm,
являющийся членом структуры
shmid_ds,
которая определяет сегмент.
Структура shmid_ds имеет такую форму:
struct shmid_ds {
struct ipc_perm shm_perm; /* права операции */
int shm_segsz; /* размер сегмента (в байтах) */
time_t shm_atime; /* время последнего подключения */
time_t shm_dtime; /* время последнего отключения */
time_t shm_ctime; /* время последнего изменения */
unsigned short shm_cpid; /* идентификатор процесса создателя */
unsigned short shm_lpid; /* идентификатор последнего пользователя */
short shm_nattch; /* количество подключений */
};
struct ipc_perm {
key_t key;
ushort uid; /* действующие идентификаторы владельца и группы euid и egid */
ushort gid;
ushort cuid; /* действующие идентификаторы создателя euid и egid */
ushort cgid;
ushort mode; /* младшие 9 битов shmflg */
ushort seq; /* номер последовательности */
};
When creating a new shared memory segment,
the system call initializes the shmid_ds data structure
При создании нового сегмента разделяемой памяти
системный вызов инициализирует структуру данных shmid_ds
следующим образом:
устанавливаемые значения
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
становится равным
нулю.
shm_ctime
устанавливается на текущее время.
Если сегмент уже существет, то права доступа подтверждаются, а проверка производится для
того, чтобы убедиться, что сегмент не помечен на удаление.
СИСТЕМНЫЕ ВЫЗОВЫ
fork()
После выполнения команды
fork()
дочерний процесс наследует подключаемые к нему разделяемые сегменты памяти.
exec()
После выполнения команды
exec()
все подключаемые к процессу разделяемые сегменты памяти отключаются от него,
но не удаляются.
exit()
По завершении
exit()
все подключенные разделяемые сегменты памяти отключаются (но не удаляются).
ВОЗВРАЩАЕМЫЕ ЗНАЧЕНИЯ
При удачном завершении вызова возвращается идентификатор сегмента
shmid,
и -1 при ошибке.
НАЙДЕННЫЕ ОШИБКИ
При ошибке переменная
errno
приобретает одно из следующих значений:
EINVAL
если создается новый сегмент, а size < SHMMIN или
size > SHMMAX, либо новый сегмент не был создан.
Сегмент с данным ключем существует, но size больше чем размер этого сегмента.
EEXIST
если значение
IPC_CREAT | IPC_EXCL
было указано, а сегмент уже существует.
ENOSPC
если все возможные идентификаторы сегментов уже распределены
(SHMMNI)
или если размер выделяемого сегмента превысит системные лимиты
(SHMALL).
ENOENT
если не существует сегмента для ключа key, а значение
IPC_CREAT
не указано.
EACCES
если у пользователя нет прав доступа к сегменту разделяемой памяти.
ENOMEM
если в памяти нет свободного для сегмента пространства.
ЗАМЕЧАНИЯ
IPC_PRIVATE
является не полем, а типом
key_t.
Если это специфическое значение используется для
key,
то системный вызов игнорирует все, кроме 9-и младших битов
shmflg,
и создает новый сегмент разделяемой памяти.
Ниже приведены ограничения для сегментов разделяемой памяти, которые могут отразиться
на вызове
shmget.
SHMALL
Максимальное количество страниц разделяемой памяти зависит от настроек системы.
SHMMAX
Максимальный размер сегмента в байтах зависит от системных настроек (обычно это 4M).
SHMMIN
Минимальный размер сегмента в байтах зависит от системных настроек (обычно он равен
одному байту, поэтому
PAGE_SIZE
яляется минимальным эффективным размером).
SHMMNI
Максимальное количество сегментов разделяемой памяти зависит от настроек системы
(сейчас оно равно 4096, было 128 до версии Linux 2.3.99).
От настроек не зависит количество сегментов, подключаемых процессом
(SHMSEG).
НАЙДЕННЫЕ ОШИБКИ
Выбор названия IPC_PRIVATE был неудачен, и IPC_NEW
более понятно поясняет смысл функции.
СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, SVID. SVr4 описывает дополнительное условие ошибки EEXIST.
До версии 2.3.30 Linux будет возвращать EIDRM для
shmget
на сегменте разделяемой памяти, назначенного на удаление.