Читаем Linux: Полное руководство полностью

КомандаНазначение
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. Это копия внутренней структуры данных семафора.

Указатель на массив array используется командами GETALL и SETALL для получения или установки значений всех семафоров во множестве.

Последние два члена объединения специфичны только для Linux — в других UNIX-системах вы их не найдете. Эти элементы использует ядро.

В случае успеха системный вызов semctl() возвращает натуральное число, а в случае ошибки -1. Переменная errno равна:

♦ EACCESS — не хватает полномочий;

♦ EFAULT — адрес arg ошибочен;

♦ EIDRM — множество помечено для удаления:

♦ EINVAL — неправильный аргумент semid;

♦ EPERM — у вас нет прав для выполнения команды cmd;

♦ ERANGE — значение семафора вышло за пределы допустимых значений.

Пример получения значения семафора с номером N из множества sid:

int val;

val=semctl(sid, N, GETVAL, 0);

Предположим, что нам нужно вывести состояние всех трех имеющихся принтеров:

int c, val;

for (c=0; x<3; c++) {

val=semctl(sid,c,GETVAL,0);

printf("Принтер %d: %d\n",c,val);

}

А вот код инициализации всех семафоров множества semid:

union semun opts;

int c;

opts.val = 1; /* первоначальное значение семафоров */

for (c=0;c<5;c++) semctl(semid, c, SETVAL, opts);

Довольно часто возникают определенные сложности с установкой прав доступа к множеству семафоров. Рассмотрим следующий код, позволяющий установить права доступа к множеству semid. Права доступа задаются в виде строки, например, «0660».

void sem_change_mode(int semid, char *mode) {

 int res;

 struct semid_ds semds;

 union semun opts;

 /* Нужно указать нашу локальную копию структуры */

 opts.buf = &semds

 if ((res = semctl(semid, 0, IPC_STAT, opts)) == -1) {

  printf("Error");

  exit(1);

 }

 printf("Старые права доступа %o\n",

 opts.buf->sem_perm.mode);

 /* Изменяем права доступа */

 sscanf(mode, "%ho", &opts.buf->sem_perm.mode);

 /* Обновляем внутреннюю структуру */

Перейти на страницу:

Все книги серии Полное руководство

Похожие книги