Обратите внимание: в структуре есть указатель на первый семафор. Тип указателя — sem. Данный тип описывает семафор:
struct sem {
short sempid; /* pid последней операции */
ushort semval; /* текущее значение семафора */
ushort semncnt; /* число процессов, ожидающих
освобожд. рес. */
ushort semzcnt; /* число процессов, ожидающих
освоб. всех рес. */
};
♦ sem_pid
PID процесса, который произвел последнюю операцию над семафором.
♦ sem_semval
Текущее значение семафора.
♦ sem_semncnt
Число процессов, ожидающих увеличения значения семафора, то есть освобождения ресурсов.
♦ sem_semzcnt
Число процессов, ожидающих освобождения всех ресурсов.
26.6.1. Создание множества семафоров
Для создания множества семафоров или подключения к уже существующему множеству используется системный вызов semget():
int semget(key_t key, int nsems, int semflg);
Первый аргумент — это ключ IPC, который, как обычно, создается системным вызовом ftok(). Он сравнивается с ключами других семафоров и в зависимости от значения semflg решается, создавать новое множество или подключиться к уже существующему. Значение semflg:
♦ IPC_CREAT — создать новое множество семафоров;
♦ IPC_EXCL — при использовании с IPC_CREAT порождает ошибку, если семафор уже существует.
При создании семафора, как и при создании очереди сообщений, мы можем указать права доступа:
IPC_CREAT | 0660
Второй аргумент системного вызова semget() задает требуемое количество семафоров. Оно ограничено в файле sem.h:
#define SEMMSL 32 /* <= 512 */
Данный аргумент игнорируется, если вы подключаетесь к уже существующему множеству, а не создаете новое.
Функция semget() возвращает идентификатор семафора или -1 в случае ошибки. Переменная errno
устанавливается следующим образом:
♦ EACCESS — у вас не хватает полномочий для выполнения операции;
♦ EEXISTS — множество существует, его нельзя создать;
♦ EIDRM — множество помечено для удаления;
♦ ENOENT — множество не существует, не было ни одной операции IPC_CREAT;
♦ ENOMEM — не хватает памяти;
♦ ENOSPC — достигнуто максимальное количество семафоров.
Функция для открытия существующего семафора может выглядеть так:
void open_sem(int *sid, key_t key) {
if ((*sid = semget(key, 0, 0666)) == -1) {
printf("Семафор не существует !!!!\n");
exit(1);
}
}
Для создания множества семафоров можно использовать следующую функцию:
void create_sem(int *sid, key_t key, int n) {
int c=0; /* счетчик */
union semun sems;
if (n > SEMMSL) {
printf("Превышен лимит. Максимальное число семафоров %d\n", SEMMSL);
exit(1);
}
if ((*sid =
semget(key, n, IPC_CREAT|IPC_EXCL|0666)) == -1) {
printf("Множество уже существует\n");
exit(1);
}
sems.val = SEM_RESOURCE_MAX;
/* Инициализируем все элементы одним значением */
semctl(*sid, c, SETALL, sems);
/* Если нужно установить разные значения,
нужно использовать SETVAL, например
for (c=0; c
semctl(*sid, c, SETVAL, sems);
*/
}
26.6.2. Выполнение операций над семафорами
Для выполнения операций над множеством семафоров служит системный вызов semop():
int semop(int semid, struct sembuf *sops, unsigned nsops);
Первый аргумент — это идентификатор семафора, возвращаемый вызовом semget(). Второй — это массив операций, которые нужно выполнить над семафорами. Последний аргумент — это количество операций в массиве.
Второй аргумент представляет собой массив типа sembuf:
struct sembuf {
ushort sem_num; /* номер семафора в массиве */
short sem_op; /* операция над семафором */
short sem_flg; /* флаги */
};
♦ sem_num
Номер семафора, над которым нужно выполнить операцию
♦ sem_op
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии