struct sem *sem_base; /*указатель на массив семафоров в наборе */
ushort sem_nsems; /* количество семафоров в наборе */
time_t sem_otime; /* время последнего вызова semop(); */
time_t sem_ctime; /* время создания последнего IPC_SET */
};
Структура ipc_perm была описана в разделе 3.3. Она содержит разрешения доступа для данного семафора.
Структура sem представляет собой внутреннюю структуру данных, используемую ядром для хранения набора значений семафора. Каждый элемент набора семафоров описывается так:
struct sem {
ushort_t semval; /* значение семафора, неотрицательно */
short sempid; /* PID последнего процесса, вызвавшего semop(), SETVAL, SETALL */
ushort_t semncnt; /* количество ожидающих того, что значение семафора превысит текущее */
ushort_t semzcnt; /* количество ожидающих того, что значение семафора станет равным 0*/
};
Обратите внимание, что sem_base представляет собой указатель на массив структур типа sem — по одному элементу массива на каждый семафор в наборе.
Помимо текущих значений всех семафоров набора в ядре хранятся еще три поля данных для каждого семафора: идентификатор процесса, изменившего значение семафора последним, количество процессов, ожидающих увеличения значения семафора, и количество процессов, ожидающих того, что значение семафора станет нулевым.
ПРИМЕЧАНИЕ
В стандарте Unix 98 данная структура не имеет имени. Приведенное выше имя (sem) взято из реализации System V.
Любой конкретный семафор в ядре мы можем воспринимать как структуру semid_ds, указывающую на массив структур sem. Если в наборе два элемента, мы получим картину, изображенную на рис. 11.1. На этом рисунке переменная sem_nsems имеет значение 2, а каждый из элементов набора идентифицируется индексом ([0] или [1]).
Рис. 11.1. Структуры данных ядра для набора семафоров из двух элементов
11.2. Функция semget
Функция semget создает набор семафоров или обеспечивает доступ к существующему.
#include
int semget(key_t
/* Возвращает неотрицательный идентификатор в случае успешного завершения, –1 – в случае ошибки */
Эта функция возвращает целое значение, называемое идентификатором семафора, которое затем используется при вызове функций semop и semctl.
Аргумент
Аргумент
При создании нового семафора инициализируются следующие поля структуры semid_ds:
■ поля uid и cuid структуры sem_perm устанавливаются равными действующему идентификатору пользователя процесса, а поля guid и cgid устанавливаются равными действующему идентификатору группы процесса;
■ биты разрешений чтения-записи аргумента
■ поле sem_otime устанавливается в 0, а поле sem_ctime устанавливается равным текущему времени;
■ значение sem_nsems устанавливается равным
■ структуры sem для каждого из семафоров набора не инициализируются. Это происходит лишь при вызове semctl с командами SETVAL или SETALL.
Инициализация значения семафора
В комментариях к исходному коду в издании этой книги 1990 года неправильно утверждалось, что значения семафоров набора инициализируются нулем при вызове semget с созданием нового семафора. Хотя в некоторых системах это действительно происходит, гарантировать подобное поведение ядра нельзя. Более старые реализации System V вообще не инициализировали значения семафоров, оставляя их содержимое таким, каким оно было до выделения памяти.