SHMCTL(2) Руководство программиста Linux SHMCTL(2)

ИМЯ

shmctl - управление общей памятью System V

ОБЗОР

#include <sys/ipc.h> #include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

ОПИСАНИЕ

Вызов shmctl() выполняет управляющую операцию, указанную в cmd, над общим сегментом памяти System V, чей идентификатор задан в shmid.

В аргументе buf содержится указатель на структуру shmid_ds, определённую в <sys/shm.h> следующим образом:

struct shmid_ds {

    struct ipc_perm shm_perm;    /* владелец и права */

    size_t          shm_segsz;   /* размер сегмента (байты) */

    time_t          shm_atime;   /* время последнего подключения */

    time_t          shm_dtime;   /* время последнего отключения */

    time_t          shm_ctime;   /* время последнего изменения */

    pid_t           shm_cpid;    /* PID создателя */

    pid_t           shm_lpid;    /* PID последнего выполнявшего

                                    shmat(2)/shmdt(2) */

    shmatt_t        shm_nattch;  /* текущее количество подключений */

    ...
};

Структура ipc_perm определена следующим образом (значения полей устанавливаются с помощью IPC_SET):

struct ipc_perm {

    key_t          __key;    /* ключ, передаваемый в shmget(2) */

    uid_t          uid;      /* эффективный UID владельца */

    gid_t          gid;      /* эффективный GID владельца */

    uid_t          cuid;     /* эффективный UID создателя */

    gid_t          cgid;     /* эффективный GID создателя */

    unsigned short mode;     /* права + флаги SHM_DEST и

                                SHM_LOCKED */

    unsigned short __seq;    /* порядковый номер */
};

Возможные значения cmd:

Копирует информацию из структуры данных ядра, связанной с shmid, в структуру shsid_ds, расположенную по адресу buf. Вызывающий должен иметь права на чтение общего сегмента памяти.
Записывает значения некоторых полей структуры shmid_ds, указанной в buf, в структуру данных ядра, связанную с общим сегментом памяти, обновляя при этом поле shm_ctime. Могут измениться следующие поля: shm_perm.uid, shm_perm.gid и shm_perm.mode (младшие 9 битов). Эффективный UID вызывающего процесса должен совпадать с UID владельца (shm_perm.uid) или создателя (shm_perm.cuid) общего сегмента памяти, или вызывающий должен иметь привилегии.
Помечает сегмент как удалённый. Сегмент будет удалён только после того как от него отключится последний процесс (т.е. когда поле shm_nattch из связанной структуры shmid_ds станет равно нулю). Вызывающий должен быть владельцем, создателем или иметь соответствующие привилегии. Аргумент buf игнорируется.
Если сегмент помечен на удаление, то в поле shm_perm.mode устанавливается (нестандартный) флаг SHM_DEST в связанной структуре данных, которая возвращается при операции IPC_STAT.
Вызывающий должен удостовериться, что сегмент в конечном итоге удалён; иначе ошибочные страницы останутся в памяти или в пространстве подкачки.
Смотрите также описание /proc/sys/kernel/shm_rmid_forced в proc(5).
Возвращает параметры и информацию о системных максимальных значениях общей памяти в структуре, указанной в buf. Данная структура имеет тип shminfo (то есть, требуется приведение типов) и определена в <sys/shm.h>, если определён макрос тестирования свойств _GNU_SOURCE:
struct shminfo {

    unsigned long shmmax; /* максимальный размер

                             сегмента */

    unsigned long shmmin; /* минимальный размер сегмента;

                             всегда 1 */

    unsigned long shmmni; /* максимальное количество

                             сегментов */

    unsigned long shmseg; /* максимальное количество

                             сегментов, к которому может

                             подключиться; процесс

                             не используется в ядре */

    unsigned long shmall; /* макс. количество страниц

                             общей памяти в системе */
};
Значения shmmni, shmmax и shmall можно изменить с помощью файлов в /proc с теми же именами; подробней см. proc(5).
Возвращает структуру shm_info, чьи поля содержат информацию о системных ресурсах, использованных общей памятью. Эта структура определена в <sys/shm.h>, если определён макрос тестирования свойств _GNU_SOURCE:
struct shm_info {

    int           used_ids; /* количество используемых в

                               данный момент сегментов */

    unsigned long shm_tot;  /* общее количество общих

                               страниц памяти */

    unsigned long shm_rss;  /* количество общих страниц,

                               находящихся в памяти */

    unsigned long shm_swp;  /* количество страниц памяти в

                               пространстве подкачки */

    unsigned long swap_attempts; /* не используется,

                                    начиная с Linux 2.4 */

    unsigned long swap_successes; /* не используется,

                                     начиная с Linux 2.4 */
};
Возвращает структуру shmid_ds как в операции IPC_STAT. Однако аргумент shmid является не идентификатором сегмента, а индексом во внутреннем массиве ядра, в котором содержится информации о всех общих сегментов памяти в системе.
Возвращает структуру shmid_ds как для SHM_STAT. Однако shm_perm.mode не проверяется на доступность чтения для shmid, что означает, что эту операцию может выполнять пользователь (как и любой пользователь, который может прочитать эту же информацию из /proc/sysvipc/shm).

Вызывающий может запретить или разрешить размещение общего сегмента памяти в пространство подкачки с помощью следующих значений cmd:

Запрещает подкачку общего сегмента памяти. После включения блокировки вызывающий должен считать сбойными все страницы, наличие которых требуется. Если сегмент заблокирован, то в поле shm_perm.mode устанавливается (нестандартный) флаг SHM_LOCKED в связанной структуре, которая возвращается при операции IPC_STAT.
Разблокирует сегмент, разрешая выполнение подкачки.

В ядрах до версии 2.6.10 только привилегированный процесс мог использовать SHM_LOCK и SHM_UNLOCK. Начиная с ядра версии 2.6.10 непривилегированный процесс может использовать эти операции, если его эффективный UID совпадает с UID владельца или создателя сегмента и (для SHM_LOCK) количество блокируемой памяти находится в пределах ресурса RLIMIT_MEMLOCK (см. setrlimit(2)).

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении операции IPC_INFO или SHM_INFO возвращается индекс самого последнего использованного элемента внутреннего массива ядра, в котором записывается информация о всех общих сегментах памяти (эта информация может быть использована в повторяющихся операциях SHM_STAT или SHM_STAT_ANY для получения информации о всех общих сегментах памяти системы). При успешном выполнении операции SHM_STAT возвращается идентификатор общего сегмента памяти, чей индекс был указан в shmid. При успешном выполнении других операций возвращается 0.

В случае ошибки возвращается -1 и значение errno устанавливается соответствующим образом.

ОШИБКИ

Указана операция IPC_STAT или SHM_STAT, но в shm_perm.mode не установлено право на чтение shmid, и вызывающий процесс не имеет мандата CAP_IPC_OWNER в пространстве имён пользователя, который управляет его пространством имён IPC.
Значение аргумента cmd равно IPC_SET или IPC_STAT, но адрес, указанный в buf, недоступен.
Значение shmid указывает на удалённый идентификатор.
Значение shmid содержит недопустимый идентификатор, или cmd содержит недопустимую команду. Или (для SHM_STAT или SHM_STAT_ANY) индекс shmid ссылается на элемент массива, который в данный момент не используется.
(в ядрах, начиная с 2.6.9) Указана операция SHM_LOCK и размер блокируемого сегмента таков, что общее количество байт, блокируемое общими сегментами памяти, превысило бы ограничение, установленное для действительного идентификатора пользователя вызывающего процесса. Этот лимит определён мягким ограничителем ресурса RLIMIT_MEMLOCK (см. setrlimit(2)).
Попытка выполнить IPC_STAT, но значения GID или UID слишком велики для помещения в структуру, на которую указывает buf.
Попытка выполнить IPC_SET или IPC_RMID, но эффективный пользовательский идентификатор вызывающего процесса не равен идентификатору создателя (shm_perm.cuid) или владельца (shm_perm.uid) и процесс не привилегированный (Linux: не имеет мандата CAP_SYS_ADMIN).
Или (в ядрах до 2.6.9) процесс не имеет привилегий (Linux: не имеет мандата CAP_IPC_LOCK) для выполнения SHM_LOCK или SHM_UNLOCK. Начиная с Linux 2.6.9 эта ошибка также возникает, если значение RLIMIT_MEMLOCK равно 0 и вызывающий не имеет привилегий.

СООТВЕТСТВИЕ СТАНДАРТАМ

POSIX.1-2001, POSIX.1-2008, SVr4.

ЗАМЕЧАНИЯ

Включение файлов <sys/types.h> и <sys/ipc.h> не требуется в Linux или любых версий POSIX. Однако, некоторые старые реализации требуют включения данных заголовочных файлов, и это также требуется по SVID. В приложениях, которые нужно перенести на такие старые системы, может потребоваться включить данных заголовочные файлы.

Операции IPC_INFO, SHM_STAT и SHM_INFO используются программой ipcs(1) для получения информации о выделенных ресурсах. В будущем для этого может быть задействован интерфейс файловой системы /proc.

Linux разрешает процессу подключаться (shmat(2)) к общему сегменту память, который уже помечен как удалённый с помощью shmctl(IPC_RMID). Это свойство недоступно в других реализациях UNIX; в переносимых приложениях лучше не использовать это свойство.

В Linux 2.2 различные поля struct shmid_ds имели тип short. В Linux 2.4 тип был изменён на long. Для задействования преимуществ этого изменения необходима перекомпиляция программы с glibc-2.1.91 или более поздней версией (ядро различает старые и новые вызовы по флагу IPC_64 в аргументе cmd).

СМОТРИТЕ ТАКЖЕ

mlock(2), setrlimit(2), shmget(2), shmop(2), capabilities(7), svipc(7)

2019-03-06 Linux