Случай 2: положительное значение sem_op

Это соответствует традиционной операции 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);

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: