Именованные семафоры linux с

Именованные семафоры linux с

Семафор представляет собой целое число, значение которого никогда не будет меньше нуля. Над семафорами выполняются две операции: увеличение значения семафора на единицу (sem_post(3)) и уменьшение значения семафора на единицу (sem_wait(3)). Если значение семафора равно нулю, то операция sem_wait(3) блокирует работу до тех пор, пока значение не станет больше нуля.

Есть два вида семафоров POSIX: именованные семафоры и безымянные семафоры.

Именованные семафоры Именованные семафоры отличают по именам вида /имя — строка (с null в конце) до NAME_MAX-4 (т. е., 251) символов, состоящая из начальной косой черты и одного или нескольких символов (символ косой черты не допускается). Два процесса могут работать с одним семафором указав его имя в sem_open(3).

Функция sem_open(3) создаёт новый именованный семафор или открывает существующий. После открытия семафора с ним можно работать посредством sem_post(3) и sem_wait(3). Когда процесс закончил использовать семафор, его можно закрыть с помощью sem_close(3). Когда все процессы закончили использовать семафор, его можно удалить из системы с помощью sem_unlink(3).

Безымянные семафоры (семафоры в памяти) Безымянные семафоры не имеют имени. Семафор размещается в области памяти, которая доступна нескольким нитям (общий семафор для нитей) или процессам (общий семафор для процессов). Общий семафор для нитей размещается в области памяти, которая доступна из нитей процесса, например в глобальной переменной. Общий семафор для процессов должен размещаться в области общей памяти (например, в сегменте общей памяти System V, созданной с помощью shmget(2), или в объекте общей памяти POSIX, созданном с помощью shm_open(3)).

Перед началом использования безымянный семафор должны быть проинициализирован с помощью sem_init(3). После этого с ним можно работать через sem_post(3) и sem_wait(3). Если семафор больше не нужен, то семафор нужно уничтожить с помощью sem_destroy(3) (но до освобождения выделенной для него памяти).

Далее в разделе описываются особенности реализации семафоров POSIX в Linux.

Версии

Устойчивость

Компоновка

Доступ к именованным семафорам через файловую систему

Начиная с Linux 2.6.19, для управления доступом к объектам конкретным пользователям или группам на файлы в этом каталоге могут быть применены ACL.

Источник

Знакомимся с семафорами в Linux

Перевод статьи подготовлен в преддверии старта курса «Administrator Linux.Basic».

Семафор – это механизм, который позволяет конкурирующим процессам и потокам работать с общими ресурсами и помогает в решении различных проблем синхронизации таких как гонки, дедлоки (взаимные блокировки) и неправильное поведение потоков.

Для решения этих проблем в ядре присутствуют такие средства как мьютексы, семафоры, сигналы и барьеры.

Есть три вида семафоров:

  1. Бинарные семафоры (binary semaphore)
  2. Семафоры-счетчики (counting semaphore)
  3. Массивы семафоров (semaphore set)

Просмотр состояния IPC

С помощью команд, приведенных ниже можно получить информацию о текущем состоянии средств межпроцессного взаимодействия (inter-process communication, IPC).

Активные массивы семафоров

Отображение информации об активных массивах семафоров.

Сегменты разделяемой памяти

Просмотр информации об активных сегментах разделяемой памяти.

Лимиты

Команда ipcs -l отображает лимиты разделяемой памяти, семафоров и сообщений.

Разделяемая память

Команда ниже отображает разделяемую память.

Создатели ресурсов

Команда отображает пользователя и группу владельца и создателя ресурса.

Использование средств IPC

В примере, приведенном ниже, параметр -u отображает сводку об использовании всех средств IPC.

При остановке сервисов семафоры и сегменты разделяемой памяти должны также удаляться. Если они не удаляются, то это можно сделать с помощью команды ipcrm, передав идентификатор IPC-объекта.

Можно также изменить лимиты семафоров, используя sysctl .

Источник

Русские Блоги

Многопоточность в Linux — семафоры и мьютексы Posix решают проблемы производителей и потребителей

Семафор Posix

Семафор Posix

Знаменитый семафор

Анонимный семафор

sem_open

sem_init

sem_close

sem_destroy

sem_unlink

sem_wait

sem_post

Знаменитый семафор

Это похоже на использование IPC типа Posix: имя идентифицируется в форме / somename, и может быть только один /, а общая длина не может превышать NAME_MAX-4 (то есть, 251).

Знаменитые семафоры Posix необходимо создавать или открывать с помощью функции sem_open. Операциями PV являются sem_wait и sem_post, которые можно закрыть с помощью sem_close и удалить с помощью sem_unlink.

Читайте также:  Как запустить службу политики диагностики windows

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

Анонимный семафор

Анонимные семафоры существуют только в памяти и требуют, чтобы процессы, использующие семафоры, имели доступ к памяти, это означает, что их можно применять только к потокам в одном и том же процессе или в разных процессах.

Потоки, которые отображают одинаковое содержимое памяти в свое адресное пространство.

Анонимные семафоры должны быть инициализированы с помощью sem_init. Второй параметр pshared функции sem_init определяет разделение потоков (pshared = 0) или разделение процессов (pshared! = 0), а также

Вы можете использовать sem_post и sem_wait для работы. Перед освобождением разделяемой памяти анонимный семафор должен быть уничтожен с помощью sem_destroy.

Работа с семафором Posix PV

Операция ожидания уменьшает семафор на 1, если счетчик семафоров изначально равен 0, произойдет блокировка;

Операция post добавляет 1 к семафору. Когда вызывается sem_post, если во время вызова sem_wait происходит блокировка процесса, то процесс будет разбужен, а счетчик семафоров sem_post, увеличенный на 1, будет снова уменьшен на sem_wait

Posix mutex

Взаимоисключающие блокировки используют простой метод блокировки для управления атомарными операциями над общими ресурсами. Этот мьютекс имеет только два состояния, то есть блокировка / разблокировка, которые можно рассматривать как определенное значение

Глобальные переменные в смысле. Только один поток может одновременно управлять определенным мьютексом, и поток с заблокированным состоянием может работать с общим ресурсом. Если другие потоки хотят заблокировать один

Если мьютекс уже заблокирован, поток будет блокироваться, пока заблокированный поток не освободит мьютекс. Можно сказать, что эта блокировка взаимного исключения гарантирует, что каждый поток входит в общие ресурсы по порядку.

Атомные операции.

Среди них мьютекс можно разделить на быстрый мьютекс (мьютекс по умолчанию), рекурсивный мьютекс и мьютекс с обнаружением ошибок. Разница между этими тремя блокировками заключается в том, что другие потоки, не имеющие блокировки мьютекса, надеются получить

Стоит ли блокировать и ждать, когда будет достигнут мьютекс. Быстрая блокировка означает, что вызывающий поток будет блокироваться, пока поток, которому принадлежит блокировка мьютекса, не будет разблокирован. Рекурсивный мьютекс может успешно вернуться и увеличить вызов

Сколько раз поток блокирует мьютекс, и мьютекс обнаружения ошибок — это неблокирующая версия быстрого мьютекса, которая немедленно возвращается и возвращает сообщение об ошибке.

Проблемы производителей и потребителей

Существует буферная зона (ограниченная буферная зона, то есть: определенная емкость), для производителей: чтобы определить при производстве продуктов, текущий

Склад, этот буфер заполнен?

Если он заполнен, то производитель блокирует p (sem_full), и всякий раз, когда мы производим продукт, значение счетчика этого семафора уменьшается на 1.

Если склад не заполнен, это означает, что мы можем производить продукты. Как только продукт произведен, это означает, что склад не пуст.

v (sem_empty), на данный момент это сказать потребителям, что теперь можно потреблять

Кроме того, при производстве продуктов может быть несколько производителей, поэтому буфер будет работать. Тогда буфер также должен быть взаимоисключающим для доступа.

Итак, здесь мы также использовали p (mutex), v (mutex)

Как указано выше: это то, что производитель должен сделать

Может быть несколько производителей, поэтому может быть несколько потребителей

Тогда задача, которую должны выполнить потребители:

Определить, является ли текущий буфер (склад) пустым (p (sem_empty))

Если он пуст, он не сможет потреблять продукт, ему нужно ждать, пока производитель отправит сигнал потребителю (то есть v (sem_empty)

Количество увеличивается на 1, что означает, что здесь есть продукт)

Тогда, если есть продукт, я могу потреблять продукт

Как только продукт будет потреблен, он увеличит емкость склада на 1 (v (sem_full))

Точно так же, когда мы потребляем продукты, мы также должны посетить p (mutex), v (mutex)

Итак, в начале мы можем производить продукты, но не можем потреблять продукты, поэтому мы говорим: начальное значение sem_full — это емкость склада (предполагается, что

10)

sem_full(10)

sem_empty(0)

Spin Lock и чтение-запись блокировки

Спин-блокировки аналогичны мьютексным, но их производительность выше, чем мьютексным.

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

Спин-блокировки и мьютекс-блокировки. Важное отличие состоит в том, что, когда поток применяется для спин-блокировки, поток не будет приостановлен, даже если поток не может получить блокировку,

Он находится в состоянии ожидания занятости (другими словами: процессор занят) постоянно подает заявку на блокировку

Читайте также:  Реестра для windows phone

Следовательно, спин-блокировка не может использоваться для приложений с длительным временем ожидания, обычно для приложений и приложений с коротким временем ожидания (некоторые приложения с высокими требованиями в реальном времени)

Если время ожидания велико, процессор находится в состоянии ожидания, тратя впустую процессор.

Блокировка чтения-записи

Блокировка чтения-записи также сравнивается с блокировкой мьютекса: если ни один поток не удерживает данную блокировку чтения-записи для записи, то любое количество потоков может удерживать блокировку чтения-записи для

Чтение (то есть: пока ни один поток не заблокирует блокировку в режиме записи, другие потоки могут заблокировать блокировку в режиме чтения)

Блокировка чтения-записи называется разделяемой блокировкой, когда она используется для чтения (то есть поток блокирует разделяемую блокировку, тогда другие потоки также могут удерживать разделяемую блокировку)

Кабель чтения-записи, используемый для записи, называется эксклюзивной блокировкой,

Независимо от того, является ли поток блокировкой чтения или блокировки записи, в это время другим потокам не разрешается запись в блокировку, пока один поток добавляет блокировку чтения-записи.

Тогда на этот раз мы не можем применять эксклюзивные замки.

Источник

Блокировки чтения-записи, условные переменные, барьеры и семафоры-счетчики

Барьеры

Барьер ( barrier ) — примитив синхронизации, применяемый главным образом в вычислительных задачах MPI/OpenMP. Существуют также примеры его применения в других задачах, но как правило это также задачи вычислительного характера. При создании барьера необходимо указать количество нитей N , необходимое для перехода через барьер . Нити, подходящие к барьеру, вызывают функцию pthread_barrier_wait(3C) . Если количество нитей, ожидающих возле барьера, меньше N-1 , нить блокируется. Когда набирается N нитей, все они разблокируются и продолжают исполнение .

При разблокировании в одной из нитей pthread_barrier_wait(3C) возвращает значение PTHREAD_BARRIER_SERIAL_THREAD , а в остальных нитях — 0. Рассмотрим расчет видеокадра многопоточной программой на многопроцессорной машине. Нити, завершившие расчет своей части изображения, блокируются на барьере. Когда расчет изображения завершен, одна из нитей (получившая PTHREAD_BARRIER_SERIAL_THREAD ) переключает видеоконтекст, то есть показывает изображение пользовтаелю, и нити продолжают расчеты.

Барьеры полезны для синхронизации нитей, выполняющих части одной и той же работы, например параллельные вычисления. Они позволяют гарантировать, что даже при неравномерной загрузке системы нити будут выполнять равный объем работы в единицу времени.

Семафоры-счетчики

Исторически, семафоры-счетчики были одним из первых примитивов синхронизации. В старых учебниках они известны под названием «семафоры Дийкстры». Семафор представляет собой целочисленную переменную, над которой определены две операции , post и wait .

Операция wait пытается вычесть единицу из флаговой переменной семафора. Если значение флаговой переменной больше 0 , то происходит обычное вычитание и нить, выполнившая операцию wait , продолжает исполнение . Если значение флаговой переменной было равно 0 , то wait блокируется до тех пор, пока кто-то (скорее всего, другая нить) не увеличит значение этой переменной.

Операция post добавляет единицу к флаговой переменной семафора. Если при этом на семафоре ждала нить, операция post пробуждает эту нить.

Семафоры можно использовать в качестве примитивов взаимоисключения, при этом операция wait аналогична захвату мутекса, а операция post — операции его освобождения. Однако, в отличие от мутексов, операции post и wait не обязаны выполняться одной и той же нитью и даже не обязаны быть парными. Это позволяет использовать семафоры в различных ситуациях, которые сложно или невозможно разрешить при помощи мутексов. Иногда семафоры используют в качестве разделяемых целочисленных переменных, например в качестве счетчиков записей в очереди.

Широко известно решение задачи производитель-потребитель на двух семафорах (см. пример 7.3).

Семафоры также можно использовать для обхода проблемы инверсии приоритета . Если высокоприоритетная и низкоприоритетная нить должны взаимодействовать, иногда удается реализовать соглашение, что только низкоприоритетная нить может выполнять над семафором операцию wait , а высокоприоритетная нить может делать только post . Такое взаимодействие обычно похоже на схему производитель-потребитель с тем отличием, что производитель может терять некоторые порции данных, если потребитель за ним не успевает. При этом условии в примере 7.3 можно избавиться от семафора p.

Такое решениедовольно часто используется в системах жесткого реального времени, поэтому семафоры-счетчики считаются частью стандарта POSIX Real Time Extension , а не основного подмножества стандарта POSIX .

В Solaris функции работы с семафорами-счетчиками включены в библиотеку librt.so. Их использование требует сборки программы с ключом -lrt. В отличие от остальных функций POSIX Thread API , функции работы с семафорами и сам тип семафора не имеют префикса pthread_ .

Как и остальные примитивы взаимодействия, рассматривавшиеся ранее, семафор POSIX представляет собой непрозрачный тип данных , операции над которым должны осуществляться специальными функциями. Этот тип называется sem_t и определен в файле semaphore .h> .

Читайте также:  Linux разрешения для каталогов

Семафоры бывают двух типов — именованные и неименованные. Те и другие семафоры хранятся в переменных типа sem_t , но процедура инициализации и уничтожения этих переменных отличается.

Неименованные семафоры инициализируются функцией sem_init(3RT) . Эта функция имеет три параметра:

  • sem_t * sem — инициализируемый семафор
  • int pshared — 0 если семафор будет локальным в пределах процесса, ненулевое значение — если семафор будет разделяемым между процессами
  • unsigned intvalue — начальноезначение флаговой переменной семафора.

После работы семафор необходимо уничтожить функцией sem_destroy(3RT) .

Над семафорами определены операции sem_post(3RT) , sem_wait(3RT) , sem_trywait(3RT) , sem_timedwait(3RT) и sem_getvalue(3RT) . Операция sem_getvalue(3RT) , как сказано в системном руководстве, «получает значение семафора в некоторый неопределенный момент времени». В любом случае, очевидно, что в интервале между исполнением sem_getvalue(3RT) и проверкой значенияфлаговая переменная семафора может измениться. Поэтому тот факт, что sem_getvalue(3RT) вернул ненулевое значение , не означает, что вызов sem_wait(3RT) с этим семафором не будет заблокирован. sem_getvalue полезен главным образом в отладочных целях.

В соответствии со стандартом POSIX , если на семафоре ожидает одна или несколько нитей, sem_getvalue(3RT) вместо нуля может возвращать отрицательное значение , модуль которого равен количеству нитей. Это поведение не является обязательным и Solaris 10 этого не делает.

Именованные семафоры создаются функцией sem_open(3RT) . При помощи этой же функции можно получить доступ к уже существующему именованному семафору. Эта функция имеет два обязательных параметра и два необязательных:

  • const char * name — имя семафора. Имя должно начинаться с символа ‘ / ‘ и не должно содержать других символов ‘ / ‘. Рекомендуется, чтобы имя не превышало 14 символов. В зависимости от реализации, объект с таким именем может либо появляться либо не появляться в корневом каталогекорневой файловой системы (в Solaris и Linux не появляется). В любом случае, для создания семафора не обязательно иметь право создания файлов в корневом каталоге.
  • int flags — флаги. Может принимать значения 0 , O_CREAT и O_CREAT|O_EXCL , где O_CREAT и O_EXCL — константы, определенные в . Смысл этих значений аналогичен соответствующим значениям флагов в параметрах open(2) . 0 означает попытку доступа к уже существующему семафору, O_CREAT — доступ к существующему семафору или попытку создания, если такого семафора нет, O_EXCL — ошибку, если при попытке создания обнаруживается, что такой семафор уже существует.
  • mode_t mode — необязательный параметр, который используется, только если flags содержит бит O_CREAT . Обозначает права доступа к семафору, которые задаются девятибитовой маской доступа, похожей на маску доступа к файлам. Как и у файла, у семафора есть идентификаторы хозяина и группы. Идентификатор хозяина устанавливается равным эффективному идентификатору пользователя процесса, создавшего семафор, идентификатор группы — эффективному идентификатору группы процесса.
  • unsigned int value — необязательный параметр, который используется только если flags содержит бит O_CREAT . Содержит начальное значение флаговой переменной семафора при его создании.

Функция sem_open(3RT) возвращает указатель на семафор ( sem_t * ). При ошибке она возвращает нулевой указатель и устанавливает errno . Если процесс попытается несколько раз открыть один и тот же семафор, ему будут возвращать один и тот же указатель . Именованные семафоры всегда разделяемые между процессами. При доступе к существующему семафору проверяются права доступа по той же схеме, по которой в Unix системам проверяются права доступа к файлам. Для доступа к семафору процесс должен иметь права чтения и записи.

Для отсоединения от семафора и освобождения памяти из-под него необходимо использовать функцию sem_close(3RT) . Эта функция неявно вызывается при exit(2) и exec(2) . Однако закрытие именованного семафора процессом не прекращает существования семафора. Чтобы удалить семафор, необходимо вызвать функцию sem_unlink(3RT) . Это лишит новые процессы возможность видеть семафор как существующий (попытка исполнить sem_open с именем этого семафора без флага O_CREAT приведет к ошибке) и позволит создать новый семафор с тем же именем. Однако если в момент sem_unlink(3RT) один или несколько процессов работали с семафором, семафор продолжит свое существование до момента, пока все эти процессы не выполнят sem_close(3RT) . Исполнять sem_unlink(3RT) могут только владелец семафора и суперпользователь .

Во всем остальном именованный семафор не отличается от неименованного. Над ним можно выполнять те же операции , что и над неименованным, при помощи тех же самых функций.

Стандартного API для получения списка именованных семафоров, существующих в системе, не существует. Разумеется, полный список этих объектов существует вядре и может быть получен через API для доступа к структурам данных ядра, но эти API различаются в разных операционных системах.

Источник

Оцените статью