Чтение онлайн

на главную - закладки

Жанры

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

};

Обратите внимание, что 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 <sys/sem.h>

int semget(key_t key, int nsems, int oflag);

/* Возвращает неотрицательный идентификатор в случае успешного завершения, –1 – в случае ошибки */

Эта функция возвращает целое значение, называемое идентификатором семафора, которое затем используется при вызове функций 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 вообще не инициализировали значения семафоров, оставляя их содержимое таким, каким оно было до выделения памяти.

В большинстве версий документации ничего не говорится о начальных значениях семафоров при создании нового набора. Руководство по написанию переносимых программ X/Open XPG3 (1989) и стандарт Unix 98 исправляют это упущение и открыто утверждают, что значения семафоров не инициализируются вызовом semget, а устанавливаются только при вызове semctl (вскоре мы опишем эту функцию) с командами SETVAL (установка значения одного из семафоров набора) и SETALL (установка значений всех семафоров набора).

Необходимость вызова двух функций для создания (semget) и инициализации (semctl) набора семафоров является неисправимым недостатком семафоров System V. Эту проблему можно решить частично, указывая флаги IPC_CREAT | IPC_EXCL при вызове semget, чтобы только один процесс, вызвавший semget первым, создавал семафор, и этот же процесс должен семафор инициализировать. 

Другие процессы получают при вызове semget ошибку EEXIST, так что им приходится еще раз вызывать semget, уже не указывая флагов IPC_CREAT или IPC_EXCL.

Однако ситуация гонок все еще не устранена. Предположим, что два процесса попытаются создать и инициализировать набор семафоров с одним элементом приблизительно в один и тот же момент времени, причем оба они будут выполнять один и тот же фрагмент кода:

1 oflag = IPC_CREAT | IPC_EXCL | SVSEM_MODE;

2 if ((semid = semget(key, 1, oflag)) >= 0) { /* успешное завершение, этот процесс должен инициализировать семафор */

3 arg.val = 1;

4 Semctl(semid, 0, SETVAL, arg);

5 } else if (errno == EEXIST) { /* уже существует, поэтому просто открываем семафор */

6 semid = Semget(key, 1, SVSEM_MODE);

7 } else

8 err_sys("semget error");

9 Semop(semid, …); /* уменьшаем значение семафора на 1 */

При этом может произойти вот что:

1. Первый процесс выполняет строки 1-3, а затем останавливается ядром.

2. Ядро запускает второй процесс, который выполняет строки 1, 2, 5, 6 и 9.

Поделиться:
Популярные книги

Выйду замуж за спасателя

Рам Янка
1. Спасатели
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Выйду замуж за спасателя

Пушкарь. Пенталогия

Корчевский Юрий Григорьевич
Фантастика:
альтернативная история
8.11
рейтинг книги
Пушкарь. Пенталогия

Газлайтер. Том 5

Володин Григорий
5. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 5

Вперед в прошлое 6

Ратманов Денис
6. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 6

Гримуар темного лорда II

Грехов Тимофей
2. Гримуар темного лорда
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Гримуар темного лорда II

Вторая жизнь майора. Цикл

Сухинин Владимир Александрович
Вторая жизнь майора
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Вторая жизнь майора. Цикл

На цепи

Уваров
1. На цепи
Старинная литература:
прочая старинная литература
5.00
рейтинг книги
На цепи

Журнал «Если», 2002 № 08

Андерсон Кевин Джей
114. Журнал Если
Фантастика:
научная фантастика
5.00
рейтинг книги
Журнал «Если», 2002 № 08

Проклятье бездны

Трофимов Ерофей
4. Бродяга
Фантастика:
боевая фантастика
5.00
рейтинг книги
Проклятье бездны

Студент из прошлого тысячелетия

Еслер Андрей
2. Соприкосновение миров
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Студент из прошлого тысячелетия

Неучтенный элемент. Том 6

NikL
6. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 6

Родословная. Том 4

Ткачев Андрей Юрьевич
4. Линия крови
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Родословная. Том 4

Адвокат

Константинов Андрей Дмитриевич
1. Бандитский Петербург
Детективы:
боевики
8.00
рейтинг книги
Адвокат

Вперед в прошлое 8

Ратманов Денис
8. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 8