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

Пример работы с семафорами:

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

возможности системного вызова 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);

}


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