Лекции по курсу "Системное программирование для UNIX". Литвинов Д.Г. - 68 стр.

UptoLike

Составители: 

68
Если sem_op положителен, то его значение добавляется к семафору. Это
соответствует возвращению ресурсов множеству семафоров приложения. Ресурсы
всегда нужно возвращать множеству семафоров, если они больше не используются!
Наконец, если sem_op равен нулю, то вызывающий процесс будет усыплен
(sleep()), пока значение семафора не станет нулем. Это соответствует ожиданию того,
что ресурсы будут использованы на 100%. Хорошим примером был бы демон,
запущенный с суперпользовательскими правами, динамически регулирующий размеры
множества семафоров, если оно достигло стопроцентного использования.
Чтобы пояснить вызов semop, вспомним нашу комнату с принтерами. Пусть мы
имеем только один принтер, способный выполнять только одно задание за раз. Мы
создаем множество семафоров из одного семафора (только один принтер) и
устанавливаем его начальное значение в 1 (только одно задание за раз).
Каждый раз, посылая задание на принтер, нам нужно сначала убедиться, что он
свободен. Мы делаем это, пытаясь получить от семафора единицу ресурса. Заполним
массив sembuf, необходимый для выполнения операции:
struct sembuf sem_lock = { 0, -1, IPC_NOWAIT };
Трансляция вышеописанной инициализации структуры добавит -1 к семафору 0
из множества семафоров. Другими словами, одна единица ресурсов будет получена от
конкретного (нулевого) семафора из нашего множества. IPC_NOWAIT установлен,
поэтому либо вызов пройдет немедленно, либо будет провален, если принтер занят.
Рассмотрим пример инициализации функции sembuf:
if(semop(sid, %sem_lock, 1) == -1)
perror("semop");
Третий аргумент (nsops) говорит, что мы выполняем только одну операцию
(есть только одна структура sembuf в нашем массиве операций). Аргумент sid является
идентификатором для нашего множества семафоров.
Когда задание на принтере выполнится, необходимо вернуть ресурсы обратно
множеству семафоров, чтобы принтером могли пользоваться другие.
struct sembuf sem_unlock = { 0, 1, IPC_NOWAIT };
Трансляция вышеописанной инициализации структуры добавляет 1 к семафору
номер 0 множества семафоров. Другими словами, одна единица ресурсов будет
возвращена множеству семафоров.
int semctl ( int semid, int semnum, int cmd, union semun arg )
Функция возвращает положительное число в случае успеха, -1 - в случае
ошибки. Переменная errno может принимать следующие значения:
EACCESS доступ отклонен;
EFAULT адрес, указанный аргументом arg, ошибочен;
EIDRM множество семафоров удалено;
EINVAL множество не существует или неправильный semid;
EPERM EUID не имеет привилегий для cmd в arg;
ERANGE значение семафора вышло за пределы допустимых значений.
Функция выполняет операции, управляющие множеством семафоров. Вызов
semctl используется для осуществления управления множеством семафоров.
Первый аргумент semctl() является ключом (в нашем случае возвращаемым
вызовом semget). Второй аргумент (semun) - это номер семафора, над которым
совершается операция. По существу, он может быть понят как индекс на множестве
семафоров, где первый семафор представлен нулем.
Аргумент cmd представляет собой команду, которая будет выполнена над
множеством. Здесь снова присутствуют IPC_STAT/IPC_SET вместе с множеством
дополнительных команд, специфичных для множеств семафоров:
IPC_STAT Берет структуру semid_ds для множества и запоминает ее по адресу
          Если sem_op положителен, то его значение добавляется к семафору. Это
соответствует возвращению ресурсов множеству семафоров приложения. Ресурсы
всегда нужно возвращать множеству семафоров, если они больше не используются!
          Наконец, если sem_op равен нулю, то вызывающий процесс будет усыплен
(sleep()), пока значение семафора не станет нулем. Это соответствует ожиданию того,
что ресурсы будут использованы на 100%. Хорошим примером был бы демон,
запущенный с суперпользовательскими правами, динамически регулирующий размеры
множества семафоров, если оно достигло стопроцентного использования.
          Чтобы пояснить вызов semop, вспомним нашу комнату с принтерами. Пусть мы
имеем только один принтер, способный выполнять только одно задание за раз. Мы
создаем множество семафоров из одного семафора (только один принтер) и
устанавливаем его начальное значение в 1 (только одно задание за раз).
          Каждый раз, посылая задание на принтер, нам нужно сначала убедиться, что он
свободен. Мы делаем это, пытаясь получить от семафора единицу ресурса. Заполним
массив sembuf, необходимый для выполнения операции:
       struct sembuf sem_lock = { 0, -1, IPC_NOWAIT };
       Трансляция вышеописанной инициализации структуры добавит -1 к семафору 0
из множества семафоров. Другими словами, одна единица ресурсов будет получена от
конкретного (нулевого) семафора из нашего множества. IPC_NOWAIT установлен,
поэтому либо вызов пройдет немедленно, либо будет провален, если принтер занят.
Рассмотрим пример инициализации функции sembuf:
       if(semop(sid, %sem_lock, 1) == -1)
          perror("semop");
        Третий аргумент (nsops) говорит, что мы выполняем только одну операцию
(есть только одна структура sembuf в нашем массиве операций). Аргумент sid является
идентификатором для нашего множества семафоров.
        Когда задание на принтере выполнится, необходимо вернуть ресурсы обратно
множеству семафоров, чтобы принтером могли пользоваться другие.
       struct sembuf sem_unlock = { 0, 1, IPC_NOWAIT };
       Трансляция вышеописанной инициализации структуры добавляет 1 к семафору
номер 0 множества семафоров. Другими словами, одна единица ресурсов будет
возвращена множеству семафоров.
       int semctl ( int semid, int semnum, int cmd, union semun arg )
        Функция возвращает положительное число в случае успеха, -1 - в случае
ошибки. Переменная errno может принимать следующие значения:
EACCESS         доступ отклонен;
EFAULT          адрес, указанный аргументом arg, ошибочен;
EIDRM           множество семафоров удалено;
EINVAL          множество не существует или неправильный semid;
EPERM           EUID не имеет привилегий для cmd в arg;
ERANGE          значение семафора вышло за пределы допустимых значений.
        Функция выполняет операции, управляющие множеством семафоров. Вызов
semctl используется для осуществления управления множеством семафоров.
        Первый аргумент semctl() является ключом (в нашем случае возвращаемым
вызовом semget). Второй аргумент (semun) - это номер семафора, над которым
совершается операция. По существу, он может быть понят как индекс на множестве
семафоров, где первый семафор представлен нулем.
        Аргумент cmd представляет собой команду, которая будет выполнена над
множеством. Здесь снова присутствуют IPC_STAT/IPC_SET вместе с множеством
дополнительных команд, специфичных для множеств семафоров:
IPC_STAT        Берет структуру semid_ds для множества и запоминает ее по адресу


       68