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

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

Жанры

Основы программирования в Linux
Шрифт:

Другой способ описания семафора — считать, что переменная

sv
, равная
true
, когда доступна критическая секция, уменьшается на единицу с помощью
P(sv)
и становится равна
false
, когда критическая секция занята, и увеличивается на единицу операцией
V(sv)
, когда критическая секция снова доступна. Имейте в виду, что обычная переменная, которую вы уменьшаете и увеличиваете на единицу, не годится, т.к. в языках С, С++, C# или практически в любом традиционном языке программирования у вас нет возможности сформировать единую атомарную операцию, проверяющую, равна ли переменная
true
, и если это так, изменяющую ее значение
на
false
. Именно эта функциональная возможность делает операции с семафором особенными.

Теоретический пример

С помощью простого теоретического примера можно посмотреть, как действует семафор. Предположим, что у вас есть два процесса: proc1 и proc2, оба нуждающиеся в некоторый момент выполнения в монопольном доступе к базе данных. Вы определяете один бинарный семафор

sv
, который стартует со значением 1 и доступен обоим процессам. Далее обоим процессам нужно выполнить одну и ту же обработку для доступа к критической секции программного кода; эти два процесса могут быть двумя разными выполняющимися экземплярами одной и той же программы.

Оба процесса совместно используют переменную-семафор

sv
. Как только один процесс выполнил операцию
P(sv)
, он получил семафор и может войти в критическую секцию программы. Второму процессу вход в критическую секцию запрещен, т.к., когда он попытается выполнить операцию
P(sv)
, он вынужден будет ждать до тех пор, пока первый процесс не покинет критическую секцию и не выполнит операцию
V(sv)
, освобождающую семафор.

Требуемый псевдокод у обоих процессов идентичен:

semaphore sv = 1;

loop forever {

 P(sv);

 critical code section;

 V(sv);

 noncritical code section;

}

Код на удивление прост, потому что определение операций

P
и
V
наделяет их большими функциональными возможностями.

Рис. 14.1 

На рис. 14.1 показана схема действующих операций

P
и
V
, напоминающих ворота в критических секциях программного кода.

Реализация семафоров в Linux

Теперь, когда вы увидели, что такое семафоры и как они действуют в теории, можно рассмотреть, как их свойства реализованы в ОС Linux. Интерфейс тщательно проработан и предлагает гораздо больше возможностей, чем обычно требуется. Все функции семафоров в Linux оперируют массивами семафоров общего вида, а не одним двоичным семафором. На первый взгляд кажется, что такой подход все усложняет, но если процесс нуждается в блокировке нескольких ресурсов, способность оперировать массивом семафоров — большое подспорье. В этой главе мы сосредоточимся на применении одиночных семафоров, поскольку в большинстве случаев это все, что вам нужно.

Далее приведены объявления функций семафоров:

#include <sys/sem.h>

int semctl(int sem_id, int sem_num, int command, ...);

int semget(key_t key, int num_sems, int sem_flags);

int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);

Примечание

Обычно заголовочный файл sys/sem.h опирается на два других заголовочных файла: sys/types.h и sys/ipc.h. Как правило, они автоматически включаются в программу файлом sys/sem.h и вам не нужно задавать

их явно в директивах
#include
.

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

Обратите внимание на то, что параметр

key
действует во многом как имя файла, т.к. он тоже представляет ресурс, который программы могут использовать и кооперироваться при этом, если соблюдают соглашение об общем имени для него. Аналогичным образом идентификатор, возвращаемый функцией
semget
и применяемый другими функциями, совместно использующими память, очень похож на файловый поток
FILE*
, возвращаемый функцией
fopen
и представляющий собой значение, применяемое процессом для доступа к совместно используемому файлу. Как и в случае файлов, у разных процессов будут разные идентификаторы семафоров, несмотря на то, что они ссылаются на один и тот же семафор. Такое применение ключа и идентификаторов — общее для всех средств IPC, обсуждаемых здесь, несмотря на то, что каждое средство применяет независимые ключи и идентификаторы.

semget

Функция

semget
создает новый семафор или получает ключ существующего семафора.

int semget(key_t key, int num_sems, int sem_flags);

Первый параметр

key
— целочисленное значение, позволяющее несвязанным процессам обращаться к одному и тому же семафору. Ко всем семафорам осуществляется непрямой доступ с помощью программы, предоставляющей ключ, для которого система затем генерирует идентификатор семафора. Ключ семафора применяется только в функции
semget
. Все остальные функции семафора используют идентификатор семафора, возвращаемый функцией
semget
.

Существует особое значение ключа семафора

IPC_PRIVATE
, которое предназначено для создания семафора, доступ к которому получает только процесс-создатель, но такой семафор редко бывает полезен. Для создания нового семафора следует задавать уникальное ненулевое целое число.

Параметр

num_sems
определяет количество требуемых семафоров. Почти всегда он равен 1.

Параметр

sem_flags
— набор флагов, очень похожих на флаги функции open. Младшие девять байтов — права доступа к семафору, ведущие себя, как права доступа к файлу. Кроме того, для создания нового семафора с помощью поразрядной операции
OR
их можно объединить со значением
IPC_CREAT
. Не считается ошибкой наличие флага
IPC_CREAT
и задание ключа существующего семафора. Флаг
IPC_CREAT
безмолвно игнорируется, если в нем нет нужды. Можно применять флаги
IPC_CREAT
и
IPC_EXCL
для гарантированного получения нового уникального семафора. Если семафор уже существует, функция вернет ошибку.

Функция

semget
вернет в случае успеха положительное (ненулевое) значение, представляющее собой идентификатор, применяемый остальными функциями семафора. В случае ошибки возвращается -1.

semop

Функция semop применяется для изменения значения семафора.

int semop(int sem_id, struct sembuf *sem_ops, size_t num_sem_ops);

Первый параметр

sem_id
— идентификатор семафора, возвращенный функцией
semget
. Второй параметр
sem_ops
— указатель на массив структур, у каждой из которых есть, по крайней мере, следующие элементы:

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

Бояръ-Аниме. Газлайтер. Том 33

Володин Григорий Григорьевич
33. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Бояръ-Аниме. Газлайтер. Том 33

Ваше Сиятельство 14

Моури Эрли
14. Ваше Сиятельство
Фантастика:
боевая фантастика
аниме
фэнтези
гаремник
5.00
рейтинг книги
Ваше Сиятельство 14

#НенавистьЛюбовь

Джейн Анна
Любовные романы:
современные любовные романы
6.33
рейтинг книги
#НенавистьЛюбовь

Камень. Книга 3

Минин Станислав
3. Камень
Фантастика:
фэнтези
боевая фантастика
8.58
рейтинг книги
Камень. Книга 3

Дважды одаренный. Том V

Тарс Элиан
5. Дважды одаренный
Фантастика:
аниме
альтернативная история
городское фэнтези
5.00
рейтинг книги
Дважды одаренный. Том V

Звездная Кровь. Изгой VII

Елисеев Алексей Станиславович
7. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
технофэнтези
рпг
фантастика: прочее
попаданцы
5.00
рейтинг книги
Звездная Кровь. Изгой VII

Железный Воин Империи VII

Зот Бакалавр
7. Железный Воин Империи
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Железный Воин Империи VII

Паутина

Макоули Пол Дж.
Фантастика:
детективная фантастика
6.00
рейтинг книги
Паутина

Геном хищника. Книга третья

Гарцевич Евгений Александрович
3. Я - Легенда!
Фантастика:
боевая фантастика
рпг
попаданцы
5.00
рейтинг книги
Геном хищника. Книга третья

Адвокат Империи 2

Карелин Сергей Витальевич
2. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 2

Я снова князь. Книга XXIII

Дрейк Сириус
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я снова князь. Книга XXIII

Лейб-хирург

Дроздов Анатолий Федорович
2. Зауряд-врач
Фантастика:
альтернативная история
7.34
рейтинг книги
Лейб-хирург

Лекарь Империи 5

Карелин Сергей Витальевич
5. Лекарь Империи
Фантастика:
городское фэнтези
аниме
героическая фантастика
попаданцы
5.00
рейтинг книги
Лекарь Империи 5

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...