next up previous contents
Next: Операции над множествами семафоров. Up: Семафоры. Previous: Создание множеств семафоров.   Contents

Управление семафорами с помощью semctl.

В справочной статье semctl синтаксис данного системного вызова описан так:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semctl (int semid, int semnum, int cmd, arg);

union semun {

  int val;

  struct semid_ds *buf;

  ushort *array;

  } arg;

Результат системного вызова semctl в случае успешного завершения зависит от выполняемого управляющего действия. Как правило он равен 0, но четыре действия (GETVAL, GETPID, GETNCNT и GETZCNT) являются исключениями. При возникновении ошибки всегда возвращается -1.

Аргументы semid и semnum определяют множество или отдельный семафор, над которым выполняется управляющее действие. В качестве аргумента semid должен выступать идентификатор множества семафоров, предварительно полученный при помощи системного вызова semget. Аргумент semnum задает номер семафора в множестве. Семафоры нумеруются с нуля.

Назначение аргумента arg зависит от управляющего действия, которое определяется значением аргумента cmd. Допустимы следующие действия:

Чтобы выполнить управляющее действие IPC_SET или IPC_RMID, процесс должен иметь действующий идентификатор пользователя, равный либо идентификаторам создателя или владельца очереди, либо идентификатору суперпользователя. Для выполнения управляющих действий SETVAL и SETALL требуется право на изменение, а для выполнения остальных действий - право на чтение.

Пример работы с семафорами (рис. 20):

/* Программа иллюстрирует

возможности системного вызова semctl()

(управление семафорами) */

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#define MAXSETSIZE 25

 

main ()

{

  extern int errno;

  struct semid_ds semid_ds;

  int length, rtrn, i, c;

  int semid, semnum, cmd, choice;

  union semun {

    int val;

    struct semid_ds *buf;

    ushort array [MAXSETSIZE];

   } arg;

  

  /* Инициализация указателя на структуру данных */

  arg.buf = &semid_ds;

  /* Ввести идентификатор множества семафоров */

  printf ("Введите ид-р множества семафоров: ");

  scanf ("%d", &semid);

 

  /* Выбрать требуемое управляющее действие */

  printf ("\nВведите номер требуемого действия:\n");

  printf (" GETVAL = 1\n");

  printf (" SETVAL = 2\n");

  printf (" GETPID = 3\n");

  printf (" GETNCNT = 4\n");

  printf (" GETZCNT = 5\n");

  printf (" GETALL = 6\n");

  printf (" SETALL = 7\n");

  printf (" IPC_STAT = 8\n");

  printf (" IPC_SET = 9\n");

  printf (" IPC_RMID = 10\n");

  printf (" Выбор = ");

  scanf ("%d", &cmd);

 

  /* Проверить значения */

  printf ("идентификатор = %d, команда = %d\n",

          semid, cmd);

  /* Сформировать аргументы и выполнить вызов */

  switch (cmd) {

      case 1: /* Получить значение */

              printf ("\nВведите номер семафора: ");

              scanf ("%d", &semnum);

              /* Выполнить системный вызов */

              rtrn = semctl (semid, semnum, GETVAL, 0);

              printf ("\nЗначение семафора = %d\n", rtrn);

              break;

      case 2: /* Установить значение */

              printf ("\nВведите номер семафора: ");

              scanf ("%d", &semnum);

              printf ("\nВведите значение: ");

              scanf ("%d", &arg.val);

              /* Выполнить системный вызов */

              rtrn = semctl (semid, semnum, SETVAL, arg.val);

              break;

      case 3: /* Получить ид-р процесса */

              rtrn = semctl (semid, 0, GETPID, 0);

              printf ("\Последнюю операцию выполнил: %d\n",rtrn);

              break;

      case 4: /* Получить число процессов, ожидающих

              увеличения значения семафора */

              printf ("\nВведите номер семафора: ");

              scanf ("%d", &semnum);

              /* Выполнить системный вызов */

              rtrn = semctl (semid, semnum, GETNCNT, 0);

              printf ("\nЧисло процессов = %d\n", rtrn);

              break;

      case 5: /* Получить число процессов, ожидающих

              обнуления значения семафора */

              printf ("Введите номер семафора: ");

              scanf ("%d", &semnum);

              /* Выполнить системный вызов */

              rtrn = semctl (semid, semnum, GETZCNT, 0

              printf ("\nЧисло процессов = %d\n", rtrn);

              break;

      case 6: /* Опросить все семафоры */

              /* Определить число семафоров в множестве */

              rtrn = semctl (semid, 0, IPC_STAT, arg.buf);

              length = arg.buf->sem_nsems;

              if (rtrn == -1) goto ERROR;

              /* Получить и вывести значения всех

              семафоров в указанном множестве */

              rtrn = semctl (semid, 0, GETALL, arg.array);

              for (i = 0; i < length; i++)

                 printf (" %d", arg.array [i]);

              break;

      case 7: /* Установить все семафоры */

              /* Определить число семафоров в множестве */

              rtrn = semctl (semid, 0, IPC_STAT, arg.buf);

              length = arg.buf->sem_nsems;

              if (rtrn == -1) goto ERROR;

              printf ("\nЧисло семафоров = %d\n", length);

              /* Установить значения семафоров множества */

              printf ("\nВведите значения:\n");

              for (i = 0; i < length; i++)

                 scanf ("%d", &arg.array [i]);

              /* Выполнить системный вызов */

              rtrn = semctl (semid, 0, SETALL, arg.array);

              break;

      case 8: /* Опросить состояние множества */

              rtrn = semctl (semid, 0, IPC_STAT, arg.buf);

              printf ("\nИдентификатор пользователя = %d\n",

                    arg.buf->sem_perm.uid);

              printf ("Идентификатор группы = %d\n",

                    arg.buf->sem_perm.gid);

              printf ("Права на операции = 0%o\n",

                    arg.buf->sem_perm.mode);

              printf ("Число семафоров в множестве = %d\n",

                    arg.buf->sem_nsems);

              printf ("Время последней операции = %d\n",

                    arg.buf->sem_otime);

              printf ("Время последнего изменения = %d\n",

                    arg.buf->sem_ctime);

              break;

      case 9: /* Выбрать и изменить поле

              ассоциированной структуры данных */

              /* Опросить текущее состояние */

              rtrn = semctl (semid, 0, IPC_STAT, arg.buf);

              if (rtrn == -1) goto ERROR;

              printf ("\nВведите номер поля, ");

              printf ("которое нужно изменить: \n");

              printf (" sem_perm.uid = 1\n");

              printf (" sem_perm.gid = 2\n");

              printf (" sem_perm.mode = 3\n");

              printf (" Выбор = ");

              scanf ("%d", &choice);

              switch (choice) {

                   case 1: /* Изменить ид-р владельца */

                           printf ("\nВведите ид-р владельца: ");

                           scanf ("%d", &arg.buf->sem_perm.uid);

                           printf ("\nИд-р владельца = %d\n",

                                  arg.buf->sem_perm.uid);

                           break;

                   case 2: /* Изменить ид-р группы */

                           printf ("\nВведите ид-р группы = ");

                           scanf ("%d", &arg.buf->sem_perm.gid);

                           printf ("\nИд-р группы = %d\n",

                                  arg.buf->sem_perm.uid);

                           break;

                   case 3: /* Изменить права на операции */

                           printf ("\nВведите восьмеричный код прав: ");

                           scanf ("%o", &arg.buf->sem_perm.mode);

                           printf ("\nПрава = 0%o\n",

                                  arg.buf->sem_perm.mode);

                           break;

                   }

             /* Внести изменения */

             rtrn = semctl (semid, 0, IPC_SET, arg.buf);

             break;

     case 10: /* Удалить ид-р множества семафоров и

             ассоциированную структуру данных */

             rtrn = semctl (semid, 0, IPC_RMID, 0);

   }

  if (rtrn == -1) {

  /* Сообщить о неудачном завершении */

  ERROR:

        printf ("\nsemctl завершился неудачей!\n");

        printf ("\nКод ошибки = %d\n", errno);

  }

  else {

        printf ("\nmsgctl завершился успешно,\n");

        printf ("идентификатор semid = %d\n", semid);

  }

  exit (0);

}

Рис. 20. Управление семафорами.


next up previous contents
Next: Операции над множествами семафоров. Up: Семафоры. Previous: Создание множеств семафоров.   Contents
2003-12-09