shmget - присваивает идентификатор разделяемому сегменту памяти
НАЗВАНИЕshmget - присваивает идентификатор разделяемому сегменту
памяти
СИНТАКСИС
#include
#include
int shmget(key_t key, int size, int shmflg);
ОПИСАНИЕ
shmget() возвращает идентификатор разделяемому сегменту
памяти, соответствующий значению аргумента key. Создается
новый разделяемый сегмент памяти с размером, округленным в
большую сторону от величины size( кратный PAGE_SIZE), если
значение key равно IPC_PRIVATE или если значение key не
равно IPC_PRIVATE и нет идентификатора, соответствующего
key; причем, выражение shmflg&IPC_CREAT истинно. Поле
shmflg состоит из:
IPC_CREAT служит для создания нового сегмента. Если
этого флага нет, то функция shmget() будет
искать сегмент, соответствующий ключу key;
затем она проверит, имеет ли пользователь
права на получение shmid, соответствующего
этому сегменту, и удостоверится, не помечен ли
сегмент на удаление.
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; /* идентификатор эффективного пользователя и группы владельца */
ushort gid;
ushort cuid; /* идентификатор эффективного пользователя и группы создателя */
ushort cgid;
ushort mode; /* младшие 9 битов shmflg */
ushort seq; /* порядковый номер */
};
Так же, во время создания сегмента, системный вызов
инициализирует структуру сегмента разделяемой памяти
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 SHMMAX, либо новый
сегмент не был создан. Сегмент с данным
ключем существует, но size больше чем размер
этого сегмента.
EEXIST возвращается, если значение IPC_CREAT |
IPC_EXCL было указано, а сегмент уже
существует.
EIDRM возвращается, если сегмент помечен на удаление
или уже удален.
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_CREAT и
IPC_EXCL в shmflg подтверждает, что будет создан новый
сегмент разделяемой памяти, но не дает права эксклюзивного
доступа к этому сегменту.
СООТВЕТСТВИЕ СТАНДАРТАМ
SVr4, SVID. SVr4 описывает ошибку EEXIST. Ни в SVr4, ни
в SVID нет описания ошибки EIDRM.