Главная страница Взаимодействие нетривиальных процессов Каждая операция задается значением sem op, которое может быть отрицательным, нулевым или положительным. Сделаем несколько утверждений, которыми будем пользоваться при дальнейшем обсуждении: semval - текущее значение семафора (рис. 11.1); ш semncnt - количество потоков, ожидающих, пока значение семафора не станет больше текущего (рис. 11.1); ш semzcnt - количество потоков, ожидающих, пока значение семафора не станет нулевым (рис. 11.1); semadj - корректировочное значение данного семафора для вызвавшего процесса. Это значение обновляется, только если для данной операции указан флаг SEM UNDO в поле sem f 1 g структуры sembuf. Эта переменная создается в ядре для каждого указавшего флаг SEM UNDO процесса в отдельности; поле структуры с именем semadj не обязательно должно существовать; ш когда выполнение потока приостанавливается до завершения операции с семафором (мы увидим, что поток может ожидать либо обнуления семафора, либо получения семафором положительного значения), поток перехватывает сигнал и происходит возвращение из обработчика сигнала, функция semop возвращает ошибку EINTR. Используя терминологию, введенную в книге [24, с. 124], можно сказать, что функция semop представляет собой медленный системный вызов, который прерывается перехватываемыми сигналами; когда выполнение потока приостанавливается до завершения операции с семафором и этот семафор удаляется из системы другим потоком или процессом, функция semop возвращает ошибку EIDRM (identifier removed - идентификатор удален). Опишем теперь работу функции semop в зависимости от трех возможных значений поля sem op: отрицательного, нулевого и положительного. 1. Если значение semop положительно, оно добавляется к semval. Такое действие соответствует освобождению ресурсов, управляемых семафором. Если указан флаг SEM UNDO, значение sem op вычитается из значения semadj данного семафора. 2. Если значение sem op равно нулю, вызвавший поток блокируется до тех пор, пока значение семафора (semval) не станет равным нулю. Если semval уже равно О, происходит немедленное возвращение из функции. Если semval не равно нулю, то ядро увеличивает значение поля semzcnt данного семафора и вызвавший поток блокируется до тех пор, пока значение semval не станет нулевым (после чего значение semzcnt будет уменьшено на 1). Как отмечалось ранее, поток будет приостановлен, только если не указан флаг IPC NOWAIT. Если семафор будет удален в процессе ожидания либо будет перехвачен сигнал, произойдет преждевременный возврат из функции с возвращением кода ошибки. 3. Если значение sem op отрицательно, вызвавший поток блокируется до тех пор, пока значение семафора не станет большим либо равным модулю sem op. Это соответствует запрашиванию ресурсов. Если значение semval больше либо равно модулю sem op, модуль sem op вычитается из semval. Если указан флаг SEM UNDD, модуль sem op добавляется к значению поля semadj данного семафора. Если значение semval меньше модуля sem op, значение поля semncnt данного семафора увеличивается, а вызвавший поток блокируется до тех пор, пока semval не станет больше либо равно модулю sem op. Когда это произойдет, поток будет разблокирован, а модуль sem op будет отнят от semval и из значения semncnt будет вычтена единица. Если указан флаг SEM UNDO, модуль sem op добавляется к значению поля semadj данного семафора. Как отмечалось ранее, поток не будет приостановлен, если указан флаг IPC NOWAIT. Ожидание завершается преждевременно, если перехватываемый сигнал вызывает прерывание либо семафор удаляется другим потоком. ПРИМЕЧАНИЕ Если сравнить этот набор операций с теми, которые разрешены для семафоров Posix, мы увидим, что для последних определены только команды -1 (sem wait) и +1 (sem post). Для семафоров System V значение семафора может изменяться с шагом, отличным от 1, и кроме того, поток может ожидать, чтобы значение семафора стало нулевым. Эти операции являются более общими, что вместе с возможностью включения нескольких семафоров в набор делает семафоры System V более сложными, чем одиночные семафоры Posix. 11.4. Функция semctl Функция semctl предназначена для выполнения разного рода вспомогательных управляющих операций с семафорами. finclude <sys/sem.h> Int semctl(Int semid, Int senюum. Int cmd, ...I* union semun arg */); /* Возвращает неотрицательное значение в случае успешного завершения (см. в тексте). -1 - в случае ошибки */ Первый аргумент {semid) представляет собой идентификатор семафора, а semnum указывает элемент набора семафоров (0,1 и т. д. до nsems-l). Значение semnum используется только командами GETVAL, SETVAL, GETNCNT, GETZCNT и GETPID. Четвертый аргумент является дополнительным - он добавляется в зависимости от команды cmd (см. комментарии в описании объединения). Объявляется это объединение следующим образом: union semun { int val: /* используется только командой SETVAL */ struct semid ds *buf: /* используется командами IPC SET и IPC STAT */ ushort *array; /* используется командами GETALL и SETALL */ Это объединение отсутствует в системных заголовочных файлах и должно декларироваться приложением (мы определяем его в заголовочном файле unpi рс. h, листинг В.1). Оно передается по значению, а не по ссылке, то есть аргументом является собственно значение объединения, а не указатель на него. ПРИМЕЧАНИЕ - К сожалению, в некоторых системах (FreeBSD и Linux) это объединение определено в заголовочном файле <sys/sem.ii>, что затрудняет написание переносимых программ. Хотя в объявлении этого объединения в системном заголовочном файле и есть некоторый смысл, стандарт Unix 98 требует, чтобы оно каждый раз явно объявлялось приложением. Ниже приведен список поддерживаемых значений аргумента cmd. В случае успешного завершения функция возвращает О, а в случае ошибки--1, если в описании команды не сказано что-либо другое. Ж GETVAL - возвращает текущее значение semval. Поскольку значение семафора отрицательным быть не может (semval объявляется как unsigned short - беззнаковое короткое целое), в случае успешного возврата значение всегда будет неотрицательным. * SETVAL - установка значения semval равным arg. val. В случае успешного выполнения корректировочное значение этого семафора (semadj) устанавливается равным нулю для всех процессов. Я GETPID - функция возвращает текущее значение поля sempid. II GETNCNT - функция возвращает текущее значение поля semncnt. It GETZCNT - функция возвращает текущее значение поля semzcnt. * GETALL - возвращаются значения semval для всех элементов набора. Значения возвращаются через указатель arg.array, а сама функция при этом возвращает 0. Обратите внимание, что вызывающий процесс должен самостоятельно выделить массив беззнаковых коротких целых достаточного объема для хранения всех значений семафоров набора, а затем сделать так, чтобы arg.array указывал на этот массив. SETALL - установка значений semval для всех элементов набора. Значения задаются через указатель arg. array. ii I PC RMI D - удаление набора семафоров, задаваемого через идентификатор semi d. ш IPC SET - установка трех полей структуры semid ds равными соответствующим полям структуры arg.buf: sem perm.uid, sem perm.gid и sem perm.mode. Поле sem ctime структуры semid ds устанавливается равным текущему времени. ш IPC STAT - возвращение вызвавшему процессу через аргумент arg.buf текущего значения полей структуры semid ds для данного набора семафоров. Обратите внимание, что вызывающий процесс должен сначала выделить место под структуру semid ds и установить на нее указатель arg. buf. 11.5. Простые программы Поскольку семафоры System V обладают живучестью ядра, мы можем продемонстрировать работу с ними, написав несколько небольших программ, которые будут выполнять с семафорами различные действия. В промежутках между выполнением отдельных программ значения семафоров будут храниться в ядре.
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |