next up previous contents
Next: Разделяемые сегменты памяти Up: Семафоры Previous: Управление семафорами через semctl   Contents

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

Cинтаксис системного вызова semop описан так:

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semop (int semid, struct sembuf *sops,

           unsigned int nsops)

При успешном завершении результат системного вызова равен нулю; в случае неудачи возвращается -1.

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

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

struct sembuf {

  short sem_num; /* Номер семафора */

  short sem_op; /* Операция над семафором */

  short sem_flg; /* Флаги операции */

};

(см. включаемый файл <sys/sem.h>).

Номер семафора задает конкретный семафор в множестве, над которым должна быть выполнена операция.

Выполняемая операция определяется следующим образом:

Допустимые значения флагов операций (поле sem_flg):

IPC_NOWAIT
- если какая-либо операция, для которой задан флаг IPC_NOWAIT, не может быть успешно выполнена, системный вызов завершается неудачей, причем ни у одного из семафоров не будет изменено значение;
SEM_UNDO
- данный флаг задает проверочный режим выполнения операции; он предписывает аннулировать ее результат даже в случае успешного завершения системного вызова semop. Иными словами, блокировка всех операций (в том числе и тех, для которых задан флаг SEM_UNDO) выполняется обычным образом, но когда наконец все операции могут быть успешно выполнены, операции с флагом SEM_UNDO игнорируются.
Аргумент nsops специфицирует число структур в массиве. Максимально допустимый размер массива определяется системным параметром SEMOPM, т. е. в каждом системном вызове semop можно выполнить не более SEMOPM операций.

Пример работы с семафорами приведен ниже:

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

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

(операции над множеством семафоров) */

 

#include <stdio.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#define MAXOPSIZE 10

 

main ()

{

  extern int errno;

  struct sembuf sops [MAXOPSIZE];

  int semid, flags, i, rtrn;

  unsigned nsops;

 

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

  printf ("\nВведите идентификатор

          множества семафоров,");

  printf ("\nнад которым будут

          выполняться операции: ");

  scanf ("%d", &semid);

  printf ("\nИд-р множества семафоров = %d", semid);

 

  /* Ввести число операций */

  printf ("\nВведите число операций ");

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

  scanf ("%d", &nsops);

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

 

  /* Инициализировать массив операций */

  for (i = 0; i < nsops; i++) {

    /* Выбрать семафор из множества */

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

    scanf ("%d", &sops [i].sem_num);

    printf ("\nНомер = %d", sops [i].sem_num);

    /* Ввести число, задающее операцию */

    printf ("\nЗадайте операцию над семафором: ");

    scanf ("%d", &sops [i].sem_op);

    printf ("\nОперация = %d", sops [i].sem_op);

    /* Указать требуемые флаги */

    printf ("\nВведите код, ");

    printf ("соответствующий требуемым флагам:\n");

    printf (" Нет флагов = 0\n");

    printf (" IPC_NOWAIT = 1\n");

    printf (" SEM_UNDO = 2\n");

    printf (" IPC_NOWAIT и SEM_UNDO = 3\n");

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

    scanf ("%d", &flags);

    switch (flags) {

         case 0:

                 sops [i].sem_flg = 0;

                 break;

         case 1:

                 sops [i].sem_flg = IPC_NOWAIT;

                 break;

         case 2:

                 sops [i].sem_flg = SEM_UNDO;

                 break;

         case 3:

            sops [i].sem_flg = IPC_NOWAIT | SEM_UNDO;

            break;

        }

    printf ("\nФлаги = 0%o", sops [i].sem_flg);

  }

 

  /* Распечатать все структуры массива */

  printf ("\nМассив операций:\n");

  for (i = 0; i < nsops; i++) {

     printf (" Номер семафора = %d\n",

             sops [i].sem_num);

     printf (" Операция = %d\n", sops [i].sem_op);

     printf (" Флаги = 0%o\n", sops [i].sem_flg);

  }

 

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

  rtrn = semop (semid, sops, nsops);

  if (rtrn == -1) {

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

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

  }

  else {

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

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

     printf ("Возвращенное значение = %d\n", rtrn);

  }

  exit (0);

}


next up previous contents
Next: Разделяемые сегменты памяти Up: Семафоры Previous: Управление семафорами через semctl   Contents
2004-06-22