GETPID  Эта команда получает идентификатор процесса, который совершал по­следнюю операцию над семафором с индексом semnum.

  GETNCNT  Эта команда получает количество процессов, ожидающих увеличе­ния значения семафора по сравнению с текущим.

  GETZCNT  Эта команда получает количество процессов, ожидающих, пока значение семафора не станет 0.

  IPC_RMID Эта команда удаляет набор семафоров и его идентификатор. Если какие-то процессы были заблокированы в операциях с этим набором, во всех этих про­цессах соответствующие вызовы semop(2) вернут ошибку EIDRM.

semctl(2) - ПРИМЕРЫ

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

  #include <sys/types. h>

  #include <sys/ipc. h>

  #include <sys/sem. h>

  #define ANY 0

  int semid, rtn;

  struct semid_ds ds;

  ushort us[5], init_us[5] = { 0, 6, 7, 1, 4 };

  ...

  semid = semget(key, 5, IPC_CREAT | 0660);

. инициализировать один семафор из набора

  semctl(semid, 2, SETVAL, 7);

. получить значение одного семафора из набора

  /* такой же формат для GETNCNT, GETZCNT, GETPID */

  rtn = semctl (semid, 2, GETVAL, ANY);

. инициализировать все семафоры в наборе

  semctl (semid, ANY, SETALL, init_us);

. получить все значения семафоров в наборе

  semctl (semid, ANY, GETALL, us);

. изменить хозяина

  /* также изменяются права доступа */

  semctl (semid, ANY, IPC_STAT, &ds);

НЕ нашли? Не то? Что вы ищете?

  ds. sem_perm. uid = 51; /* new uid */

  semctl (semid, ANY, IPC_SET, &ds);

. удалить набор семафоров

  semctl (semid, ANY, IPC_RMID, ANY);


Инициализировать и удалить семафор - Пример

Это тот же пример, что и выше, но здесь показан код для инициализации семафора и его уда­ления. Этот фрагмент программы работает так:

32-37  Если эта программа создала набор семафоров, инициализировать его в 1. Как правило, набор семафоров должен быть удален перед выходом из программы, если его инициализация не удалась, но это здесь не показано.

54-60  Cоздатель набора семафоров может удалить его. В нашей программе, по соглаше­нию, удалением семафоров занимается тот же процесс, который их создал. Обратите внима­ние на использование "пустых" аргументов в тех местах, где соответствующие параметры системных вызовов не используются. Функция sleep(3C) задерживает удаление сема­фора на 5 секунд, так что другая программа может продолжать работу с ним.

Файл: semdemo. c

  ИНИЦИАЛИЗИРОВАТЬ И УДАЛИТЬ СЕМАФОР - ПРИМЕР

1 #include <unistd. h>

2 #include <stdlib. h>

3 #include <sys/types. h>

4 #include <sys/ipc. h>

5 #include <sys/sem. h>

6 #include <stdio. h>

7 #define  DUMMY  0

8 #define  COUNT  4

9

10 main(int argc, char *argv[])

11 {

  ...

32  if (creator) {/* initialize semaphore */

33  if (semctl(semid, 0, SETVAL, 1) == -1) {

34  perror(argv[0]);

35  exit(2);

36  }

37  }

  ...

54  if (creator) {

55  sleep(5);

56  if(semctl(semid, DUMMY, IPC_RMID, DUMMY) == -1) {

57  perror(argv[0]);

58  exit(5);

59  }

60  }

61  return(0);

62 }


Операции над семафорами

Системный вызов semop(2) производит операции над одним или более семафорами из на­бора. Операции увеличивают или уменьшают значение семафора на заданную величину, или ожидают, пока семафор не станет нулевым.

Аргументы этого системного вызова таковы:

semid Идентификатор набора семафоров.

sops Адрес массива с элементами типа struct sembuf. Каждый элемент задает одну опера­цию над одним семафором. По этому адресу должно размещаться nsops таких структур. Эта структура определена следующимобразом:

  sys/sem. h:

  struct sembuf {

  ushort sem_num; /* semaphore */

  short sem_op;  /* semaphore operation */

  short sem_flg;  /* operation flags */

  };

  Поля этой структуры имеют следующий смысл:

  sem_num Индекс семафора, над которым производится операция.

  sem_op Если это значение положительно, оно добавляется к текущему значе­нию семафора (POST).

Если sem_op отрицательно, и его абсолютное значение больше текущего значения семафора, операция обычно блокируется. Иначе, из семафора просто вычитает­ся абсолютное значение этого поля (WAIT).

Если sem_op равен нулю, операция блокируется, пока семафор не станет нулевым.

  sem_flg Это поле  задает дополнительные флаги. Нулевое значение означает, что не задано никаких флагов. Допустимы следующие флаги, объединяемые побитовым ИЛИ:

IPC_NOWAIT Если установлен этот флаг, и операция должна была бы привести к блокировке, semop(2) возвращает неуспех. Этот флаг может быть использо­ван для анализа и изменения значения семафора без блокировки.

SEM_UNDO  Если этот флаг установлен, при завершении процесса (как по exit(2), так и по сигналу), операция будет отменена. Это защищает от посмертной блокировки ресурса процессом, который ненормально завершился, не успев освободить ресурс.

Использование SEM_UNDO отменяет операцию над семафором, но не обеспечивает, что ре­сурс, защищаемый этим семафором, остался в согласованном состоянии после завершения процесса.

Кроме того, нужно иметь в виду, что отмена операций реализована в виде счетчика, в кото­ром накапливаются все значения, добавляемые и вычитаемые процессом при операциях над данным семафором. При завершении процесса этот счетчик просто вычитается из текущего значения семафора. Из этого описания должно быть ясно, что если вы используете флаг SEM_UNDO, его необходимо использовать при всех операциях над этим семафором. Если вы указываете SEM_UNDO только при операциях LOCK, но не при UNLOCK, счетчик отме­ны может просто переполниться, а его применение к семафору может привести к нежела­тельным результатам.

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

nsops Количество структур в массиве, на который указывает sops. nsops должен всегда быть больше или равен 1. Параметр prctl(1) process. max-sem-ops ограничивает максимальное количество операций в одном наборе.


Блокировка ресурса - Пример

Здесь показан фрагмент программы для захвата и освобождения ресурса. Разделяемым ре­сурсом является возможность вывода на терминал. Обычно, если два процесса одновременно пишут на терминал, то вывод обоих процессов смешивается на экране.

В этом примере программа использует семафоры, чтобы получить исключительный доступ к терминалу и напечатать текстовую строку. Если эта программа параллельно исполняется дву­мя процессами, то процессы будут использовать терминал по очереди.

Этот фрагмент программы работает следующим образом:

14-17  Эти командные структуры задают операцию захвата (вычесть 1) и операцию освобо­ждения (добавить один). Флаг SEM_UNDO используется для восстановления предыдущего значения семафора, если программа, изменившая его, ненормально завершится. Один из способов вызвать ненормальное завершение программы - нажать клавишу BREAK или DEL на терминале.

... Отсутствующий код содержит вызов semget(2) для создания набора из одного семафора и semctl(2) для установки его значения в 1 командой SETVAL.

41-44  Здесь семафор уменьшается на 1, блокируя (захватывая) ресурс.

45  Печатается сообщение о том, что ресурс заблокирован. Заметьте, что вывод не завер­шается переводом каретки, то есть это будет еще не вся строка вывода. В пропущенном коде необходимо выключить буферизацию stdio, чтобы неполные строки выводились на устрой­ство.

46  sleep(3C) изображает использование терминала. Кроме того, это освобождает процес­сор на время, пока процесс спит.

47-51  Печатается сообщение, что ресурс освобождается. Затем ресурс действительно осво­бождается увеличением значения семафора на 1.

Ниже приведена выдача двух экземпляров этой программы, запущенных в

фоновом режиме. Это может быть сделано одной командной строкой.

$ semdemo & semdemo &

12423

12424

$ [12423] locking[12423] unlocking

[12424] locking[12424] unlocking

[12423] locking[12423] unlocking

[12424] locking[12424] unlocking

[12423] locking[12423] unlocking

[12424] locking[12424] unlocking

[12423] locking[12423] unlocking

[12424] locking[12424] unlocking

Заметьте, что каждый процесс по очереди пишет полную строку на стандартный вывод, яв­ляющийся сейчас разделяемым ресурсом.

Файл: semdemo. c

  БЛОКИРОВКА РЕСУРСА - ПРИМЕР

1  #include <unistd. h>

2  #include <stdlib. h>

3  #include <sys/types. h>

4  #include <sys/ipc. h>

5  #include <sys/sem. h>

6  #include <stdio. h>

7  #define  DUMMY  0

8  #define  COUNT  4

9

10  main(int argc, char *argv[])

11  {

  ...

14  static struct sembuf lock =

15  { 0, -1, SEM_UNDO };

16  static struct sembuf unlock =

17  { 0, 1, SEM_UNDO };

  ...

39  pid = getpid();

40  for (i = 0; i < COUNT; i++ ) {

41  if (semop(semid, &lock, 1) == -1) {

42  perror(argv[0]);

43  exit(3);

44  }

45  printf("[%d] locking\t", pid);

46  sleep(1);/* terminal output being used */

47  printf("[%d] unlocking\n", pid);

48  if (semop(semid, &unlock, 1) == -1) {

49  perror(argv[0]);

50  exit(4);

51  }

52  }

  ...

62  }


Набор семафоров - Использование

Этот пример иллюстрирует использование набора семафоров, содержащего более чем один семафор. Этот набор используется для управления ресурсами печати. Существует три отдельных ресурса, и каждому из них соответствует собственный семафор в наборе. Эти ре­сурсы суть все принтеры вместе, механический принтер и лазерный принтер. Заметьте, что семафор 0, первый в наборе, инициализирован значением 2, т. к. в общем принтерном ресурсе есть два принтера. Пунктирные линии показывают связи между тремя ресурсами и тремя се­мафорами.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9