Это соответствует традиционной операции v (). Значение переменной sem_op просто прибавляется к соответствующему значению semval. Если есть процессы, ожидающие изменения значения этого семафора, то они могут продолжить выполнение, если новое значение семафора удовлетворит их условия.
Случай 3: нулевое значение sem_op
В этом случае вызов sem_op будет ждать, пока значение семафора не станет равным нулю; значение semval этим вызовом не будет изменяться. Если в переменной sem_f lg установлен флаг IPC_NOWAIT, а значение semval еще не равно нулю, то функция semop сразу же вернет сообщение об ошибке.
Флаг SEM_UNDO
Это еще один флаг, который может быть установлен в элементе sem_flg структуры sembuf. Он сообщает системе, что нужно автоматически «отменить» эту операцию после завершения процесса. Для отслеживания всей последовательности таких операций система поддерживает для семафора целочисленную переменную semadj. Важно понимать, что переменная semadj связана с процессами, и для разных процессов один и тот же семафор будет иметь различные значения semadj. Если при выполнении операции semop установлен флаг SEM_UNDO, то значение переменной sem_num просто вычитается из значения semadj. При этом важен знак переменной sem_num: значение semadj уменьшается, если значение sem_num положительное, и увеличивается, если оно отрицательное. После выхода из процесса система прибавляет все значения semadj к соответствующим семафорам и, таким образом, сводит на нет эффект от всех вызовов semop. В общем случае флаг SEM_UNDO должен быть всегда установлен, кроме тех случаев, когда значения, устанавливаемые процессом, должны сохраняться после завершения процесса.
|
|
Пример работы с семафорами
Теперь продолжим пример, который начали с процедуры initsem. Он содержит две процедуры p() и v(), реализующие традиционные операции над семафорами. Сначала рассмотрим p():
/* Процедура р.с - операция р для семафора */
#include "pv.h"
int р (int semid)
{
struct sembuf p_buf;
p_buf.sem_num = 0;
p_buf.sem_op = -1;
p_buf.sem_fig = SEM_UNDO;
if(semop(semid, &p_buf, 1) == -1)
{
perror("Ошибка операции p(semid)");
exit(1);
}
return (0);
}
Обратите внимание на то, что здесь использован флаг SEM_UNDO. Теперь рассмотрим текст процедуры v().
/* Процедура v.с - операция v для семафора */
#include "pv.h"
int v(int semid)
{
struct sembuf v_buf;
v_buf.sem_num = 0;
v_buf.sem_op = 1;
v_buf.sem_fig = SEM_UNDO;
if (semop (semid, &v_buf, 1) == 1)
{
perror("Ошибка операции v(semid)");
exit(1);
}
return (0);
}