- Создание семафора linux с
- 26.6. Семафоры
- Читайте также
- Семафоры
- Семафоры чтения-записи
- Семафоры
- Семафоры
- 12.3 СЕМАФОРЫ
- 26.6. Семафоры
- 10.13. Ограничения на семафоры
- ГЛАВА 11 Семафоры System V
- Семафоры Posix, размещаемые в памяти
- Именованные семафоры Posix
- Семафоры System V
- 4.4.2. Исключающие семафоры
- 4.4.5. Обычные потоковые семафоры
- 5.2. Семафоры для процессов
- Создание семафора linux с
- 6.4.3. Семафоры
- 6.4.4. Разделяемая память
Создание семафора linux с
Рассматриваемые в данном разделе средства позволяют процессам взаимодействовать, изменяя значения объектов, называемых семафорами. Значение семафора — это целое число в диапазоне от 0 до 32767. Поскольку во многих приложениях требуется более одного семафора, ОС UNIX предоставляет возможность создавать множества семафоров. Их максимальный размер ограничен системным парамет- ром SEMMSL. Множества семафоров создаются при помощи системного вызова semget.
Процесс, выполнивший системный вызов semget, становится владельцем / создателем множества семафоров. Он определяет, сколько будет семафоров в множестве; кроме того, он специфицирует первоначальные права на выполнение операций над множеством для всех процессов, включая себя. Впоследствии данный процесс может уступить право собственности или изменить права на операции при помощи системного вызова semctl, предназначенного для управления семафорами, однако на протяжении всего времени существования множества семафоров создатель остается создателем. Другие процессы, обладающие соответствующими правами, для выполнения прочих управляющих действий также могут использовать системный вызов semctl.
Над каждым семафором, принадлежащим множеству, при помощи системного вызова semop можно выполнить любую из трех операций:
- Увеличить значение.
- Уменьшить значение.
- Дождаться обнуления.
Для выполнения первых двух операций у процесса должно быть право на изменение, для выполнения третьей достаточно права на чтение. Чтобы увеличить значение семафора, системному вызову semop следует передать требуемое число. Чтобы уменьшить значение семафора, нужно передать требуемое число, взятое с обратным знаком; если результат получается отрицательным, операция не может быть успешно выполнена. Для третьей операции нужно передать 0; если текущее значение семафора отлично от нуля, операция не может быть успешно выполнена.
Операции могут снабжаться флагами. Флаг SEM_UNDO означает, что операция выполняется в проверочном режиме, то есть требуется только узнать, можно ли успешно выполнить данную операцию.
При отсутствии флага IPC_NOWAIT системный вызов semop может быть приостановлен до тех пор, пока значение семафора, благодаря действиям другого процесса, не позволит успешно завершить операцию (ликвидация множества семафоров также приведет к завершению системного вызова). Подобные операции называются «операциями с блокировкой» . С другой стороны, если обработка завершается неудачей и не указано, что выполнение процесса должно быть приостановлено, операция над семафором называется «операцией без блокировки» .
Системный вызов semop оперирует не с отдельным семафором, а с множеством семафоров, применяя к нему «массив операций». Массив содержит информацию о том, с какими семафорами нужно оперировать и каким образом. Выполнение массива операций с точки зрения пользовательского процесса является неделимым действием. Это значит, во-первых, что если операции выполняются, то только все вместе и, во-вторых, что другой процесс не может получить доступ к промежуточному состоянию множества семафоров, когда часть операций из массива уже выполнилась, а другая часть еще не успела.
Операционная система, разумеется, выполняет операции из массива по очереди, причем порядок не оговаривается. Если очередная операция не может быть выполнена, то эффект предыдущих операций аннулируется. Если таковой оказалась операция с блокировкой, выполнение системного вызова приостанавливается. Если неудачу потерпела операция без блокировки, системный вызов немедленно завершается, возвращая значение -1 как признак ошибки, а внешней переменной errno присваивается код ошибки.
Источник
26.6. Семафоры
Семафор — это объект IPC, управляющий доступом к общим ресурсам (устройствам). Семафоры не позволяют одному процессу захватить устройство до тех пор, пока с этим устройством работает другой процесс. Семафор может находиться в двух положениях: 0 (устройство занято) и 1 (устройство свободно).
Одиночный семафор используется редко, практически никогда. Для контроля доступа к ресурсам обычно используются множества семафоров, даже если это множество состоит всего из одного семафора. Например, пусть у нас есть три принтера. Когда вы посылаете задание на печать, диспетчер печати просматривает множество семафоров принтеров и выясняет, есть ли свободный принтер. Если да, то он начинает печатать ваше задание, если же нет, диспетчер ставит ваше задание в очередь печати.
Еще один пример использования семафоров — это счетчики ресурсов. Представим, что вместо принтера есть некий контроллер, позволяющий выполнять 100 заданий одновременно. Когда он свободен, значение семафора равно 100. По мере поступления заданий диспетчер контроллера уменьшает значение семафора на 1, а по мере их выполнения увеличивает на 1. Когда значение достигает 0, новое задание ставится в очередь до освобождения контроллера.
Как и в случае с очередями сообщений, для семафоров в ядре Linux есть своя структура — semid_ds, которая описана в файле /usr/src/linux/include/linux/sem.h:
struct ipc_perm sem_perm; /* права доступа */
time_t sem_otime; /* время последней операции */
time_t sem_ctime; /* время последнего изменения */
struct sem *sem_base; /* указатель на первый семафор */
struct wait_queue *eventn; /* очереди ожидания */
struct wait_queue *eventz;
struct sem_undo *undo; /* запросы undo в этом массиве */
ushort sem_nsems; /* номера семафоров в массиве */
Обратите внимание: в структуре есть указатель на первый семафор. Тип указателя — sem. Данный тип описывает семафор:
short sempid; /* pid последней операции */
ushort semval; /* текущее значение семафора */
ushort semncnt; /* число процессов, ожидающих
ushort semzcnt; /* число процессов, ожидающих
PID процесса, который произвел последнюю операцию над семафором.
Текущее значение семафора.
Число процессов, ожидающих увеличения значения семафора, то есть освобождения ресурсов.
Число процессов, ожидающих освобождения всех ресурсов.
Данный текст является ознакомительным фрагментом.
Продолжение на ЛитРес
Читайте также
Семафоры
Семафоры В операционной системе Linux семафоры (semaphore) — это блокировки, которые переводят процессы в состояние ожидания. Когда задание пытается захватить семафор, который уже удерживается, семафор помещает это задание в очередь ожидания (wait queue) и переводит это задание в
Семафоры чтения-записи
Семафоры чтения-записи Семафоры, так же как и спин-блокировки, могут быть типа чтения-записи. Ситуации, в которых предпочтительнее использовать семафоры чтения-записи такие же как и в случае использования спин-блокировок чтения-записи.Семафоры чтения-записи
Семафоры
Семафоры Давайте переместимся из ванной комнаты на кухню, так как это социально адаптированное помещение для одновременного обитания более чем одного человека. На кухне вы можете не пожелать, чтобы все и каждый находились бы там одновременно. В действительности вы бы,
Семафоры
Семафоры Для синхронизации процессов, а точнее, для синхронизации доступа нескольких процессов к разделяемым ресурсам, используются семафоры. Являясь одной из форм IPC, семафоры не предназначены для обмена большими объемами данных, как в случае FIFO или очередей сообщений.
12.3 СЕМАФОРЫ
12.3 СЕМАФОРЫ Поддержка системы UNIX в многопроцессорной конфигурации может включать в себя разбиение ядра системы на критические участки, параллельное выполнение которых на нескольких процессорах не допускается. Такие системы предназначались для работы на машинах AT amp;T
26.6. Семафоры
26.6. Семафоры Семафор — это объект IPC, управляющий доступом к общим ресурсам (устройствам). Семафоры не позволяют одному процессу захватить устройство до тех пор, пока с этим устройством работает другой процесс. Семафор может находиться в двух положениях: 0 (устройство
10.13. Ограничения на семафоры
10.13. Ограничения на семафоры Стандартом Posix определены два ограничения на семафоры:? SEM_NSEMS_MAX — максимальное количество одновременно открытых семафоров для одного процесса (Posix требует, чтобы это значение было не менее 256);? SEM_VALUE_MAX — максимальное значение семафора (Posix
ГЛАВА 11 Семафоры System V
ГЛАВА 11 Семафоры System V 11.1.Введение В главе 10 мы описывали различные виды семафоров, начав с:? бинарного семафора, который может принимать только два значения: 0 и 1. По своим свойствам такой семафор аналогичен взаимному исключению (глава 7), причем значение 0 для семафора
Семафоры Posix, размещаемые в памяти
Семафоры Posix, размещаемые в памяти Мы измеряем скорость работы семафоров Posix (именованных и размещаемых в памяти). В листинге А.24 приведен текст функции main, а в листинге А.23 — текст функции incr.Листинг А.23. Увеличение счетчика с использованием семафоров Posix в
Именованные семафоры Posix
Именованные семафоры Posix В листинге А.26 приведен текст функции main, измеряющей быстродействие именованных семафоров Posix, а в листинге А.25 — соответствующая функция incr.Листинг А.25. Увеличение общего счетчика с использованием именованного семафора Posix//bench/incr_pxsem2.c40 void
Семафоры System V
Семафоры System V Функция main программы, измеряющей быстродействие семафоров System V, приведена в листинге А.27, а функция incr показана в листинге А.28.Листинг А.27. Функция main для измерения быстродействия семафоров System V//bench/incr_svsem1.c1 #include «unpipc.h»2 #define MAXNTHREADS 1003 int nloop;4 struct <5 int
4.4.2. Исключающие семафоры
4.4.2. Исключающие семафоры Решение проблемы гонки заключается в том, чтобы позволить только одному потоку обращаться к очереди в конкретный момент времени. Когда поток начинает просматривать очередь, все остальные потоки вынуждены дожидаться, пока он удалит очередное
4.4.5. Обычные потоковые семафоры
4.4.5. Обычные потоковые семафоры В предыдущем примере, в котором группа потоков обрабатывает задания из очереди, потоковая функция запрашивает задания до тех пор, пока очередь не опустеет, после чего поток завершается. Эта схема работает в том случае, когда все задания
5.2. Семафоры для процессов
5.2. Семафоры для процессов Как говорилось в предыдущем разделе, процессы должны координировать свои усилия при совместном доступе к памяти. Вспомните: в разделе 4.4.5, «Обычные потоковые семафоры», рассказывалось о семафорах, которые являются счетчиками, позволяющими
Источник
Создание семафора linux с
Sven Goldt, Sven van der Meer, Skott Burkett, Matt Welsh
6.4.3. Семафоры
Семафоры лучше всего предствлять себе как счетчики, управляющие доступом к общим ресурсам. Чаще всего они используются как блокирующий механизм, не позволяющий одному процессу захватить ресурс, пока этим ресурсом пользуется другой. Семафоры часто подаются как наиболее трудные для восприятия из всех трех видов IPC-объектов. Для полного понимания, что же такое семафор, мы их немного пообсуждаем, прежде чем переходить к системным вызовам и операционной теории.
Слово «семафор» в действительности является старым железнодорожным термином, соответствующим «рукам», не дающим траекториям каров (это то, что у буржуев ездит по рельсам — перев.) пересекаться на перекрестках. То же самое можно сказать и про семафоры. Семафор в положении ON (руки пондяты вверх) если ресурс свободен и в положении OFF (руки опущены) если ресурс недоступен (должны ждать).
Этот пример неплохо показал суть работы семафора, однако важно знать, что в IPC используются множества семафоров, а не отдельные экземпляры. Разумеется, множество может содержать и один семафор, как в нашем железнодорожном примере.
Возможен другой подход к семафорам — как к счетчикам ресурсов. Приведем другой пример из жизни. Вообразим себе спулер, управляющий несколькими принтерами, каждый из которых обрабатывает по нескольку заданий. Гипотетический менеджер печати будет использовать множество семафоров для установления доступа к каждому из принтеров.
Предположим, что в корпоративной комнате имеются 5 работающих принтеров. Наш менеджер конструирует 5 семафоров — по одному на каждый принтер. Поскольку каждый принтер может обрабатывать только по одному запросу за раз, все семафоры устанавливаются в 1, что означает готовность всех принтеров печатать.
Машенька послала запрос на печать. Менеджер смотрит на семафоры и находит первый из них со значением 1. Перед тем, как Машенькин запрос попадет на физическое устройство, менеджер печати уменьшит соответствующий семафор на 1. Теперь значение семафора есть 0. В мире семафоров System V нуль означает стопроцентную занятость ресурса на семафоре. В нашем примере на принтере не будет ничего печататься, пока значение семафора не изменится.
Когда Машенька напечатала все свои плакаты, менеджер печати увеличивает семафор на 1. Теперь его значение вновь равно 1 и принтер может принимать задания снова.
Не смущайтесь тем, что все семафоры инициализируются единицей. Семафоры, трактуемые как счетчики ресурсов, могут изначально устанавливаться в любое натуральное число, не только в 0 или 1. Если бы наши принтеры умели печатать по 500 документов за раз, мы могли бы проинициализировать семафоры значением 500, уменьшая семафор на 1 при каждом поступающем задании и увеличивая после его завершения. Как вы увидите в следующей главе, семафоры имеют очень близкое отношение к разделяемым участкам памяти, играя роль сторожевой собаки, кусающей нескольких писателей в один и тот же сегмент памяти (имеется в виду машинная память).
Перед тем, как копаться в системных вызовах, коротко пробежимся по внутренним структурам данных, с которыми имеют дело семафоры.
Структура semid_ds ядра
Так же, как и для очередей сообщений, ядро отводит часть своего адресного пространства под структуру данных каждого множества семафоров. Структура определена в linux/sem.h:
Так же, как с очередями сообщений, операции с этой структурой проводятся с помощью системных вызовов, а не грязными скальпелями. Вот некоторые описания полей.
Это пример структуры ipc_perm, котораф описана в linux/ipc.h. Она содержит информацию о доступе к множеству семафоров, включая права доступа и информацию о создателе множества (uid и т.д.).
Время последней операции semop() (подробнее чуть позже).
Время последнего изменения структуры.
Указатель на первый семафор в массиве.
Число запросов undo в массиве (подробнее еще чуть позже).
Количество семафоров в массиве.
Структура sem ядра
В sem_ds есть указатель на базу массива семафоров. Каждый элемент массива имеет тип sem, который описан в linux/sem.h:
ID процесса, проделавшего последнюю операцию
Текущее значение семафора
Число процессов, ожидающих освобождения требуемых ресурсов
Число процессов, ожидающих освобождения всех ресурсов
Системный вызов semget() используется для того, чтобы создать новое множество семафоров или получить доступ к старому.
Первый аргумент semget() — это ключ (в нашем случае возвращается ftok()-ом). Он сравнивается с ключами остальных множеств семафоров, присутствующих в системе. Вместе с этим решается вопрос о выборе между созданием и подключением к множеству семафоров в зависимости от аргумента msgflg.
Создает множество семафоров, если его еще не было в системе.
При использовании вместе с IPC_CREAT вызывает ошибку, если семафор уже существует.
Если IPC_CREAT используется в одиночку, то semget() возвращает идентификатор множества семафоров — вновь созданного или с таким же ключом. Если IPC_EXCL используется совместно с IPC_CREAT, то либо создается новое множество, либо, если оно уже существует, вызов приводит к ошибке и -1. Сам по себе IPC_EXCL бесполезен, но вместе с IPC_CREAT он дает средство гарантировать, что ни одно из существующих множеств семафоров не открыто для доступа. Как и в других частях System V IPC, восьмеричный режим доступа может быть OR-нут в маску для формирования доступа к множеству семафоров.
Аргумент nems определяет число семафоров, которых требуется породить в новом множестве. Это количество принтеров в нашей корпоративной комнате. Максимальное число семафоров определяется в
Аргумент nsems игнорируется, если вы открвываете существующую очередь.
Напишем функции-переходники для открытия и создания множества семафоров.
Обратите внимание на явное задание доступа 0660. Эта незатейливая функция возвращает идентификатор множества семафоров или -1 в случае ошибки. Должны быть также заданы значение ключа и число семафоров для того, чтобы сосчитать память, необходимую для них. В примере, завершающем этот IPC_EXCL используется для определения существует множество семафоров или нет.
Системный вызов semop()
Первый аргумент semop() есть значение ключа (в нашем случае возвращается semget-ом). Второй аргумент (sops) — это указатель на массив операций, выполняемых над семафорами, третий аргумент (nsops) является количеством операций в этом массиве.
Аргумент sops указывает на массив типа sembuf. Эта структура описана в linux/sem.h следующим образом:
Номер семафора, с которым вы собираетесь иметь дело.
Выполняемая операция (положительное, отрицательное число или нуль).
Если sem_op отрицателен, то его значение вычитается из семафора (семафор уменьшается — перев.). Это соответствует получению ресурсов, которые контролирует семафор. Если IPC_NOWAIT не установлен, то вызывающий процесс засыпает, пока семафор не выдаст требуемое количество ресурсов (пока другой процесс не освободит их).
Если sem_op положителен, то его значение добавляется к семафору. Это соответствует возвращению ресурсов множеству семафоров приложения. Ресурсы всегда нужно возвращать множеству семафоров, если они больше не используются!
Наконец, если sem_op равен нулю, то вызывающий процесс будет усыплен (sleep()), пока значение семафора не станет нулем. Это соответствует ожиданию того, что ресурсы будут использованы на 100%. Хорошим примером был бы демон, запущенный с суперпользовательскими правами, динамически регулирующий размеры множества семафоров, если оно достигло стопроцентного использования.
Чтобы пояснить вызов semop, вспомним нашу комнату с принтерами. Пусть мы имеем только один принтер, способный выполнять только одно задание за раз. Мы создаем множество семафоров из одного семафора (только один принтер) и устанавливаем его начальное значение в 1 (только одно задание за раз).
Каждый раз, посылая задание на принтер, нам нужно сначала убедиться, что он свободен. Мы делаем это, пытаясь получить от семафора единицу ресурса. Давайте заполним массив sembuf, необходимый для выполнения операции:
Трансляция вышеописанной инициализации структуры добавит -1 к семафору 0 из множества семафоров. Другими словами, одна единица ресурсов будет получена от конкретного (нулевого) семафора из нашего множества. IPC_NOWAIT установлен, поэтому либо вызов пройдет немедленно, либо будет провален, если принтер занят. Рассмотрим пример инициализации sembuf-а semop-ом:
Третий аргумент (nsops) говорит, что мы выполняем только одну (1) операцию (есть только одна структура sembuf в нашем массиве операций). Аргумент sid является IPC идентификатором для нашего множества семафоров.
Когда задание на принтере выполнится, мы должны вернуть ресурсы обратно множеству семафоров, чтобы принтером могли пользоваться другие.
Трансляция вышеописанной инициализации структуры добавляет 1 к семафору номер 0 множества семафоров. Другими словами, одна единица ресурсов будет возвращена множеству семафоров.
Системный вызов semctl()
Вызов semctl используется для осуществления управления множеством семафоров. Этот вызов аналогичен вызову msgctl для очередей сообщений. Если вы сравните списки аргументов этих двух вызовов, то заметите, что они немного отличаются. Напомним, что семафоры введены скорее как множества, чем как отдельные объекты. С операциями над семафорами требуется посылать не только IPC-ключ, но и конкретный семафор из множества.
Оба системных вызова используют аргумент cmd для определения команды, которая будет выполнена над IPC-объектом. Оставшаяся разница заключается в последнем аргументе. В msgctl он представляет копию внутренней структуры данных ядра. Повторим, что мы используем эту структуру для получения внутренней информации об очереди сообщений либо для установки или изменения прав доступа и владения очередью. Для семафоров поддерживаются дополнительные команды, которые требуют данных более сложного типа в последнем аргументе. Использование объединения (union) огорчает многих новичков до состояния %(. Мы очень внимательно разберем эту структуру, чтобы не возникало никакой путаницы.
Первый аргумент semctl() является ключом (в нашем случае возвращаемым вызовом semget). Второй аргумент (semun) — это номер семафора, над которым совершается операция. По существу, он может быть понят как индекс на множестве семафоров, где первый семафор представлен нулем.
Аргумент cmd представляет собой команду, которая будет выполнена над множеством. Как вы можете заметить, здесь снова присутствуют IPC_STAT/IPC_SET вместе с кучей дополнительных команд, специфичных для множеств семафоров:
Берет структуру semid_ds для множества и запоминает ее по адресу аргумента buf в объединении semun.
Устанавливает значение элемента ipc_perm структуры semid_ds для множества.
Удаляет множество из ядра.
Используется для получения значений всех семафоров множества. Целые значения запоминаются в массиве элементов unsigned short, на который указывает член объединения array.
Выдает число процессов, ожидающих ресурсов в данный момент.
Возвращает PID процесса, выполнившего последний вызов semop.
Возвращает значение одного семафора из множества.
Возвращает число процессов, ожидающих стопроцентного освобождения ресурса.
Устанавливает значения семафоров множества, взятые из элемента array объединения.
Устанавливает значение конкретного семафора множества как элемент val объединения.
Аргумент arg вызова semсtl() является примером объединения semun, описанного в linux/sem.h следующим образом:
Определяет значение, в которое устанавливается семафор командой SETVAL.
Используется командами IPC_STAT/IPC_SET. Представляет копию внутренней структуры данных семафора, находящейся в ядре.
Указатель для команд GETALL/SETALL. Ссылается на массив целых, используемый для установки или получения всех значений семафоров в множестве.
Оставшиеся аргументы __buf и __pad предназначены для ядра и почти, а то и вовсе не нужны разработчику приложения. Эти два аргумента специфичны для LINUX-а, их нет в других системах UNIX-а.
Поскольку этот особенный системный вызов наиболее сложен для восприятия среди всех системных вызовов System V IPC, мы рассмотрим несколько его примеров в действии.
Следующий отрывок выдает значение указанного семафора. Последний аргумент (объединение) игнорируется, если используется команда GETVAL.
Возвращаясь к примеру с принтерами, допустим, что потребовалось определить статус всех пяти принтеров:
Программа пытается создать локальную копию внутренней структуры данных для множества семафоров, изменить права доступа и сIPC_SETить их обратно в ядро. Однако, первый вызов semctl-а немедленно вернет EFAULT или ошибочный адрес для последнего аргумента (объединения!). Кроме того, если бы мы не следили за ошибками для этого вызова, то заработали бы сбой памяти. Почему?
Вспомним, что команды IPC_SET/IPC_STAT используют элемент buf объединения, который является указателем на тип semid_ds. Указатели — это указатели, и ничего кроме указателей! Элемент buf должен ссылаться на некий корректный участок памяти, чтобы наша функция работала как полагается. Рассмотрим исправленную версию:
semtool: Интерактивное средство для работы с семафорами
Поведение semtool()-а зависит от аргументов командной строки, что удобно для вызова из скрипта shell-а. Позволяет делать все, что угодно, от создания и манипулирования до редактирования прав доступа и удаления множества семафоров. Может быть использовано для управления разделяемыми ресурсами через стандартные скрипты shell-а.
Синтаксис командной строки
Создание множества семафоров
semtool c (количество семафоров в множестве)
Запирание семафора
semtool l (номер семафора для запирания)
Отпирание семафора
semtool u (номер семафора для отпирания)
Изменение прав доступа (mode)
semtool m (mode)
Удаление множества семафоров
semtool d
Примеры semtool c 5
semtool l
semtool u
semtool m 660
semtool d
6.4.4. Разделяемая память
Разделяемая память может быть наилучшим образом описана как отображение участка (сегмента) памяти, которая будет разделена между более чем одним процессом. Это гораздо более быстрая форма IPC, потому что здесь нет никакого посредничества (т.е. каналов, очередей сообщений и т.п.). Вместо этого, информация отображается непосредственно из сегмента памяти в адресное пространство вызывающего процесса. Сегмент может быть создан одним процессом и впоследствии использован для чтения/записи любым количеством процессов.
Внутренние и пользовательские структуры данных
Давайте взглянем на структуру данных, поддерживаемую ядром, для разделяемых сегментов памяти.
Структура ядра shmid_ds
Так же, как для очередей сообщений и множеств семафоров, ядро поддерживает специальную внутреннюю структуру данных для каждого разделяемого сегмента памяти, который существует врутри его адресного пространства. Такая структура имеет тип shmid_ds и определена в Linux/shm.h как следующая:
Операции этой структуры исполняются посредством специального системного вызова и с ними не следует работать непосредственно. Вот описания полей, наиболее относящихся к делу:
Это образец структуры ipc_perm, который определен в Linux/ipc.h. Он содержит информацию о доступе к сегменту, включая права доступа и информацию о создателе сегмента (uid и т.п.).
Размеры сегмента (в байтах).
Время последней привязки к сегменту.
Время последней отвязки процесса от сегмента.
Время последнего изменения этой структуры (изменение mode и т.п.).
PID создавшего процесса.
PID последнего процесса обратившегося к сегменту.
Число процессов, привязанных к сегменту на данный момент.
Системный вызов shmget()
Чтобы создать новый разделяемый сегмент памяти или получить доступ к уже существующему, используется системный вызов shmget().
Этот новый вызов должен выглядеть для вас почти как старые новости. Он поразительно похож на соответствующие вызовы get для очередей сообщений и множеств семафоров.
Первый аргумент для shmget() — это значение ключа (в нашем случае возвращен посредством вызова ftok()-а). Это значение ключа затем сравнивается с существующими значениями, которые находятся внутри ядра для других разделяемых сегментов памяти. В этом отношении операция открытия или получения доступа зависит от содержания аргумента shmflg.
Создает сегмент, если он еще не существует в ядре.
При использовании совместно с IPC_CREAT приводит к ошибке, если сегмент уже существует.
Если используется один IPC_CREAT, то shmget() возвращает либо идентификатор для вновь созданного сегмента, либо идентификатор для сегмента, который уже существует с тем же значением ключа. Если вместе с IPC_CREAT используется IPC_EXCL, тогда либо создается новый сегмент, либо, если сегмент уже существует, вызов «проваливается» с -1. IPC_EXCL сам по себе бесполезен, но если он комбинируется с IPC_CREAT, то может быть использован как способ получения гарантии, что нет уже существующих сегментов, открытых для доступа.
Повторимся, (необязательный) восьмеричный доступ может быть объеденен по ИЛИ в маску доступа.
Давайте создадим функцию-переходник для обнаружения или создания разделяемого сегмента памяти:
Отметьте явное использование 0660 для прав доступа. Эта небольшая функция выдает либо идентификатор разделяемого сегмента памяти (int), либо -1 в случае ошибки. Значение ключа и заказанные размеры сегмента (в байтах) передаются в виде аргументов.
Как только процесс получает действующий идентификатор IPC для выделяемого сегмента, следующим шагом является привязка или размещение сегмента в адресном пространстве процесса.
Системный вызов shmat()
Если аргумент addr является нулем, ядро пытается найти нераспределенную область. Это рекомендуемый метод. Адрес может быть указан, но типично это используется только для облегчения работы аппаратного обеспечения или для разрешения конфликтов с другими приложениями. Флаг SHM_RND может быть OR-нут в аргумент флага, чтобы заставить переданный адрес выровняться по странице (округление до ближайшей страницы).
Кроме того, если устанавливается флаг SHM_RDONLY, то разделяемый сегмент памяти будет распределен, но помечен readonly.
Этот вызов, пожалуй, наиболее прост в использовании. Рассмотрим функцию-переходник, которая по корректному идентификатору сегмента возвращает адрес привязки сегмента:
Если сегмент был правильно привязан, и процесс имеет указатель на начало сегмента, чтение и запись в сегмент становятся настолько же легкими,как манипуляции с указателями. Не потеряйте полученное значение указателя! Иначе у вас не будет способа найти базу (начало) сегмента.
Вызов очень похож на msgctl(), выполняющий подобные задачи для очередей сообщений. Поэтому мы не будем слишком детально его обсуждать. Употребляемые значения команд следующие:
Берет структуру shmid_ds для сегмента и сохрает ее по адресу, указанному buf-ом.
Устанавливает значение ipc_perm-элемента структуры shmid_ds. Сами величины берет из аргумента buf.
Помечает сегмент для удаления.
IPC_RMID в действительности не удаляет сегмент из ядра, а только помечает для удаления. Настоящее же удаление не происходит, пока последний процесс, привязанный к сегменту, не «отвяжется» от него как следует. Конечно, если ни один процесс не привязан к сегменту на данный момент, удаление осуществляется немедленно.
Снятие привязки производит системный вызов shmdt.
После того, как разделяемый сегмент памяти больше не нужен процессу, он должен быть отсоединен вызовом shmdt(). Как уже отмечалось, это не то же самое, что удаление сегмента из ядра. После успешного отсоединения значение элемента shm_nattch структуры shmid_ds уменьшается на 1. Когда оно достигает 0, ядро физически удаляет сегмент.
shmtool: Интерактивный обработчик разделяемых сегментов памяти
Наш последний пример объектов System V IPC — это shmtool: средство командной строки для создания, чтения, записи и удаления разделяемых сегментов памяти. Так же, как и в предыдущий примерах, во время исполнения любой операции сегмент создается, если его прежде не было.
Синтаксис командной строки
Запись строк в сегмент
Получение строк из сегмента
Изменение прав доступа (mode)
shmtool w test
shmtool w «This is a test»
shmtool r
shmtool d
shmtool m 660
Источник