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 на сегменте разделяемой памяти, назначенного на удаление.

 

shmctl - производит операции по управлению разделяемыми сегментами памяти

СИНТАКСИС

#include <sys/ipc.h>

#include <sys/shm.h>

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

ОПИСАНИЕ

shmctl() позволяет пользователю получать информацию о разделяемых сегментах памяти, устанавливать владельца, группу разделяемого сегмента, права на него; эта функция может также удалить сегмент. Информация о сегменте, которая находится в shmid, возвращается в структуру 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; /* количество текущих подключений сегмента */...};

Выделенные поля в shm_perm могут быть установлены следующим образом:

struct ipc_perm { key_t key; ushort uid; /* owner euid and egid */ ushort gid; ushort cuid; /* creator euid and egid */ ushort cgid; ushort mode; /* lower 9 bits of access modes */ ushort seq; /* sequence number */};

Значения аргумента cmds могут быть следующими:

IPC_STAT

используется для копирования информации о сегменте в буфер buf. Пользователь должен иметь права на чтение сегмента read.

IPC_SET

используется для применения пользовательских изменений к содержимому полей uid, gid или mode в структуре shm_perms. Используются только младшие 9 битов mode. Поле shm_ctime тоже обновляется. Пользователь должен быть владельцем, создателем или суперпользователем процесса.

IPC_RMID

используется для пометки сегмента как удаленного. Сегмент будет удален после отключения (например, когда поле shm_nattch ассоциированной структуры shmid_ds равно нулю). Пользователь должен быть владельцем, создателем или суперпользователем процесса.

Пользователь должен удостовериться, что сегмент удален; иначе страницы, которые не были удалены, останутся в памяти или в разделе подкачки.

Также процессы с соответствующими привилегиями могут предотвратить или разрешить подкачку разделяемого сегмента памяти при помощи следующих команд cmds (применимо только для Linux):

SHM_LOCK

запретить подкачку разделяемого сегмента памяти. После блокировки страницы должны находиться в памяти.

SHM_UNLOCK

разрешить подкачку сегмента.

Процессы, которым разрешено использовать SHM_LOCK и SHM_UNLOCK при запуске их с возможностью CAP_IPC_LOCK (обычно выдаваемой только для root) или если их текущий лимит ресурсов RLIMIT_MEMLOCK не равен нулю.

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

 

СИСТЕМНЫЕ ВЫЗОВЫ

Fork()

После команды fork() дочерние процессы наследуют сегменты разделяемой памяти.

Exec()

После команды exec() все подключенные сегменты разделяемой памяти отключаются (но не удаляются).

Exit()

Если выполнена команда exit(), все сегменты разделяемой памяти отключаются (но не удаляются).

 

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

При удачном выполнении возвращается 0, а при ошибке -1.

НАЙДЕННЫЕ ОШИБКИ

В случае ошибки переменной errno присваиваются следующие значения:

EACCES

Она возникает, если запрашивается IPC_STAT, а shm_perm.modes не дает доступа msqid к чтению.

EFAULT

Аргумент cmd равен IPC_SET или IPC_STAT, а адрес, указываемый buf, недоступен.

EINVAL

Эта ошибка происходит, если shmid является неверным идентификатором сегмента или cmd является неправильной командой.

EIDRM

Эта ошибка возвращается, если shmid указывает на удаленный идентификатор.

EPERM

Эта ошибка возвращается, если была произведена попытка выполнить IPC_SET или IPC_RMID, эффективный идентификатор вызывающего процессы не является идентификатором создателя (в соответствие с shm_perm.cuid), владельца (в соответствие с shm_perm.uid) или суперпользователя.

EOVERFLOW

возвращается если запрашивается IPC_STAT, а значения gid или uid слишком велики для помещения в структуру, на которую указывает buf.

 

ЗАМЕЧАНИЯ

Многие поля в структуре struct msqid_ds Linux 2.2 были короткими, в версии 2.4 они стали длиннее. Для эффективного применения этого необходима перекомпиляция версии в glibc-2.1.91 или более позднюю версию. (Ядро различает старые и новые вызовы по флагу IPC_64 в аргументе cmd.)

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

SVr4, SVID. SVr4 описывает условия ошибки EINVAL, ENOENT, ENOSPC, ENOMEM, EEXIST. Ни в SVr4, ни в SVID не описывается ошибка EIDRM.

СМ. ТАКЖЕ

 

shmop - работа с разделяемой памятью

СИНТАКСИС

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

void *shmat(int shmid, const void * shmaddr, int shmflg );

int shmdt(const void * shmaddr );

ОПИСАНИЕ

Функция shmat подстыковывает сегмент разделяемой памяти shmid к адресному пространству вызывающего процесса. Адрес подстыковываемого сегмента определяется shmaddr с помощью одного из перечисленных ниже критериев:

Если shmaddr равен NULL, то система выбирает для подстыкованного сегмента подходящий (неиспользованный) адрес.

Если shmaddr не равен NULL, а в поле shmflg включен флаг SHM_RND, то подстыковка производится по адресу shmaddr, округленному вниз до ближайшего кратного SHMLBA. В противном случае shmaddr должен быть округленным до размера страницы адресом, к которому производится подстыковка.

Если в поле shmflg включен флаг SHM_RDONLY, то подстыковываемый сегмент будет доступен только для чтения, и вызывающий процесс должен иметь права на чтение этого сегмента. Иначе, сегмент будет доступен для чтения и записи, и у процесса должны быть соответствующие права. Сегментов "только-запись" не существует.

Флаг SHM_REMAP (специфичный для Linux) может быть указан в shmflg для обозначения того, что распределение сегмента должно замещать любые существующие распределения в диапазоне, начиная с shmaddr и до размера сегмена. (Обычно выдается ошибка EINVAL если уже существует распределение в этом диапазоне адресов.) В этом случае shmaddr не должно быть равно NULL.

Значение brk вызывающего процесса подстыковкой не изменяется. При завершении работы процесса сегмент будет отстыкован. Один и тот же сегмент может быть подстыкован в адресное пространство процесса несколько раз, как "только для чтения", так и в режиме "чтение-запись".

При удачном выполнении системный вызов shmat обновляет содержимое структуры shmid_ds, связанной с разделяемым сегментом памяти, следующим образом:

shm_atime устанавливается в текущее время.

shm_lpid устанавливается в идентификатор вызывающего процесса.

shm_nattch увеличивается на 1.

Заметьте, что пристыковка производится и в том случае, если пристыковываемый сегмент помечен на удаление.

Функция shmdt отстыковывает сегмент разделяемой памяти, находящийся по адресу shmaddr, от адресного пространства вызвающего процесса. Отстыковываемый сегмент должен быть среди пристыкованных ранее функцией shmat. Параметр shmaddr должен быть равен значению, которое возвратила соответствующая функция shmat.

При удачном выполнении системный вызов shmdt обновляет содержимое структуры shmid_ds, связанной с разделяемым сегментом памяти, следующим образом:

shm_dtime устанавливается в текущее время.

shm_lpid устанавливается в идентификатор вызывающего процесса.

shm_nattch уменьшается на 1. Если это значение становится равным 0, а сегмент помечен на удаление, то сугмент удаляется из памяти. Эта функция освобождает занятую ранее этим сегментом область памяти в адресном пространстве процесса.

 

СИСТЕМНЫЕ ВЫЗОВЫ

Fork()

При исполнении fork() дочернии процесс наследует пристыкованные сегменты разделяемой памяти.

Exec()

При исполнении exec() все подстыкованные сегменты памяти отстыковываются от процесса.

Exit()

При исполнении exit() все подстыкованные сегменты памяти отстыковываются от процесса.

 

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

При ошибке обе функции возвращают -1, а переменной errno присваивается номер ошибки. При удачном выполнении shmat возвращает адрес подстыкованного сегмента памяти, а shmdt возвращает 0.

НАЙДЕННЫЕ ОШИБКИ

При ошибке функции shmat переменная errno может принимать следующие коды ошибок:

EACCES

Вызывающий процесс не имеет прав для подстыковки заданного типа.

EINVAL

Неправильное значение shmid, не выравненное по границе страницы или неправильное значение shmaddr, или ошибка подключения к brk, или SHM_REMAP было определено, но shmaddr равно NULL.

ENOMEM

Не хватает памяти для описателя или таблиц страниц.

Функция shmdt может неудачно завершиться только в одном случае: если по адресу shmaddr, нет сегмента разделяемой памяти. В этом случае errno будет содержать EINVAL.

ЗАМЕЧАНИЯ

Для улучшемия переносимости программ рекомендуется использовать shmat с аргументом shmaddr установленным в NULL. Необходимо учитывать, что что сегмент разделяемой памяти, пристыковываемый таким способом, может быть в разных процессах пристыкова к разным адресам. Поэтому все указатели в области разделяемой памяти должны быть не абсолютными, а относительными (как правило относительно адреса начала сегмента).

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

SHMLBA

Коэффициент округления нижней границы сегмента. Должен нацело делиться на размер страницы. На настоящий момент SHMBLA равен PAGE_SIZE.

В текущей реализации не существует явного предела максимального количества подстыкованных сегментов разделяемой памяти на процесс: (SHMSEG)

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

SVr4, SVID. SVr4 описывает дополнительный код ошибки EMFILE. В SVID-v4 тип аргумента shmaddr изменен с char * на const void *, и возвращаемое значение shmat () - с char * на void *. (В Linux libc4 и libc5 в прототипе указано char *; а в glibc2 - void *.)

 

 

Typedef union semun

{

int val;

struct semid_ds *buf;

ushort *array;

} semun;

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-26 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: