Стивенс Уильям Ричард
Шрифт:
Структура ipc_perm была описана в разделе 3.3. Она содержит разрешения доступа для данного семафора.
Структура sem представляет собой внутреннюю структуру данных, используемую ядром для хранения набора значений семафора. Каждый элемент набора семафоров описывается так:
Обратите внимание, что sem_base представляет собой указатель на массив структур типа sem — по одному элементу массива на каждый семафор в наборе.
Помимо текущих значений всех семафоров набора в ядре хранятся еще три поля данных для каждого семафора: идентификатор процесса, изменившего значение семафора последним, количество процессов, ожидающих увеличения значения семафора, и количество процессов, ожидающих того, что значение семафора станет нулевым.
ПРИМЕЧАНИЕ
В стандарте Unix 98 данная структура не имеет имени. Приведенное выше имя (sem) взято из реализации System V.
Любой конкретный семафор в ядре мы можем воспринимать как структуру semid_ds, указывающую на массив структур sem. Если в наборе два элемента, мы получим картину, изображенную на рис. 11.1. На этом рисунке переменная sem_nsems имеет значение 2, а каждый из элементов набора идентифицируется индексом ([0] или [1]).
Рис. 11.1. Структуры данных ядра для набора семафоров из двух элементов
11.2. Функция semget
Функция semget создает набор семафоров или обеспечивает доступ к существующему.
Эта функция возвращает целое значение, называемое идентификатором семафора, которое затем используется при вызове функций semop и semctl.
Аргумент nsems задает количество семафоров в наборе. Если мы не создаем новый набор, а устанавливаем доступ к существующему, этот аргумент может быть нулевым. Количество семафоров в уже созданном наборе изменить нельзя.
Аргумент oflag представляет собой комбинацию констант SEM_R и SEM_A из табл. 3.3. Здесь R обозначает Read (чтение), а А — Alter (изменение). К этим константам можно логически прибавить IPC_CREAT или IPC_CREAT | IPC_EXCL, о чем мы уже говорили в связи с рис. 3.2.
При создании нового семафора инициализируются следующие поля структуры semid_ds:
■ поля uid и cuid структуры sem_perm устанавливаются равными действующему идентификатору пользователя процесса, а поля guid и cgid устанавливаются равными действующему идентификатору группы процесса;
■ биты разрешений чтения-записи аргумента oflag сохраняются в sem_perm.mode;
■ поле sem_otime устанавливается в 0, а поле sem_ctime устанавливается равным текущему времени;
■ значение sem_nsems устанавливается равным nsems;
■ структуры sem для каждого из семафоров набора не инициализируются. Это происходит лишь при вызове semctl с командами SETVAL или SETALL.
Инициализация значения семафора
В комментариях к исходному коду в издании этой книги 1990 года неправильно утверждалось, что значения семафоров набора инициализируются нулем при вызове semget с созданием нового семафора. Хотя в некоторых системах это действительно происходит, гарантировать подобное поведение ядра нельзя. Более старые реализации System V вообще не инициализировали значения семафоров, оставляя их содержимое таким, каким оно было до выделения памяти.