Первый аргумент — это идентификатор объекта IPC, второй — это массив операций. Последний аргумент semop() говорит о том, что у нас есть только одна структура типа sembuf, то есть нам нужно выполнить только одну операцию.
После выполнения задания мы должны сообщить семафору об освобождении ресурса:
struct sembuf prn_unlock ={0, 1, IPC_NOWAIT};
semop(sid, &prn_unlock, 1);
В случае успеха, когда выполнены все операции, системный вызов semop() возвращает 0. В случае ошибки возвращается -1, а errno равна:
♦ E2BIG — количество операций (аргумент nsops) превышает разрешенное число операций;
♦ EACCESS — не хватает полномочий;
♦ EAGAIN — операция не может быть выполнена (при использовании флага IPC_NOWAIT), такую операцию нужно повторить снова;
♦ EFAULT — указатель sops указывает на ошибочный адрес;
♦ EIDRM — множество помечено на удаление;
♦ EINTR — прервано сигналом;
♦ EINVAL — неверный semid;
♦ ENOMEM — не хватает памяти для создания структуры Undo-операции;
♦ ERANGE — значение семафора вышло за пределы допустимых значений.
26.6.3. Контроль семафора
Для контроля семафора используется системный вызов semctl():
int semctl(int semid, int semnum, int cmd, union semun arg);
Первый аргумент — это идентификатор семафора, второй — номер семафора во множестве семафоров (нумерация начиняется с 0). В отличие от очереди сообщений, где достаточно было указать только идентификатор очереди, при работе с семафорами нужно обязательно указывать номер конкретного семафора, над которым вы хотите выполнить операцию. Третий аргумент — это команда, которую нужно выполнить над семафором. Возможные команды представлены в таблице 26.1.
Команды управления семафорами Таблица 26.1
Команда | Назначение |
---|---|
IPC_STAT | Запоминает структуру semid_ds для множества по адресу buf объединения semun (чуть позже мы подробно рассмотрим эту структуру и объединение semun) |
IPC_SET | Устанавливает значение члена ipc_perm структуры semid_ds |
IPC_RMID | Удаляет множество |
GETALL | Позволяет получить значения всех семафоров. Значения возвращаются в виде массива unsigned short, на который указывает член объединения array |
GETNCNT | Возвращает число процессов, которые ожидают ресурсы в данный момент |
GETPID | Возвращает PID процесса, выполнившего последний вызов semop() |
GETVAL | Возвращает значение одного семафора |
GETZCNT | Возвращает число процессов, которые ожидают полного освобождения ресурса |
SETALL | Устанавливает значение семафоров. Значения берутся из члена array объединения semun |
SETVAL | Устанавливает значение конкретного семафора. Значение берется из элемента val объединения semun |
Последний аргумент — это объединение (union) аргументов, которые можно использовать для управления семафором. Рассмотрим подробнее это объединение, объявленное в файле /usr/src/linux/include/linux/sem.h
:
union semun {
int val; /* значение для SETVAL */
struct semid_ds *buf; /* буфер для IPC_STAT и IPC_SET */
ushort *array; /* массив для GETALL и SETALL */
struct seminfo *__buf; /* буфер для IPC_INFO */
void *__pad;
};
Первый член этого объединения val используется для установки значения одного семафора при использовании команды SETVAL.
Член buf используется командами IPC_STAT и IPC_SET. Это копия внутренней структуры данных семафора.