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

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

Жанры

Разработка ядра Linux (Второе издание)
Шрифт:

Использование семафоров

Функция

down_interruptible
выполняет попытку захватить данный семафор. Если эта попытка неудачна, то задание переводится в состояние ожидания с флагом
TASK_INTERRUPTIBLE
. Из материала главы 3 следует вспомнить, что такое состояние процесса означает, что задание может быть возвращено к выполнению с помощью сигнала и что такая возможность обычно очень ценная. Если сигнал приходит в тот момент, когда задание ожидает на освобождение семафора, то задание возвращается к выполнению, а функция
down_interruptible
возвращает значение
– EINTR
. Альтернативой рассмотренной функции выступает функция
down
,
которая переводит задание в состояние ожидания с флагом
TASK_UNINTERRUPTIBLE
. В большинстве случаев это нежелательно, так как процесс, который ожидает на освобождение семафора, не будет отвечать на сигналы. Поэтому функция
down_interruptible
используется значительно более широко, чем функция
down
. Да, имена этих функций, конечно, далеки от идеала.

Функция

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

Для освобождения захваченного семафора необходимо вызвать функцию

up
. Рассмотрим следующий пример.

/* объявление и описание семафора с именем mr_sem и

первоначальным значением счетчика, равным 1 */

static DECLARE_MUTEX(mr_sem);

...

if (down_interruptible(&mr_sem))

 /* получен сигнал и семафор не захвачен */

/* критический участок ... */

/* освободить семафор */

up(&mr_sem);

Полный список функций работы с семафорами приведен в табл. 9.5.

Таблица 9.5. Список функций работы с семафорами

Функция Описание
sema_init(struct semaphore*, int)
Инициализация динамически созданного семафора и установка для него указанного значения счетчика использования
init_MUTEX(struct semaphore*)
Инициализация динамически созданного семафора и установка его счетчика использования в значение 1
init_MUTEX_LOCKED (struct semaphore*)
Инициализация динамически созданного семафора и установка его счетчика использования в значение 0 (т.е. семафор изначально заблокирован)
down_interruptible(struct semaphore *)
Выполнить попытку захватить семафор и перейти в прерываемое состояние ожидания, если семафор находится в состоянии конфликта при захвате (contended)
down(struct semaphore*)
Выполнить попытку захватить семафор и перейти в непрерываемое состояние ожидания, если семафор находится в состоянии конфликта при захвате (contended)
down_trylock(struct semaphore*)
Выполнить попытку захватить семафор и немедленно возвратить ненулевое значение, если семафор находится в состоянии конфликта при захвате (contended)
up(struct semaphore*)
Освободить указанный семафор и возвратить к выполнению ожидающее задание, если такое есть

Семафоры чтения-записи

Семафоры,

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

Семафоры чтения-записи представляются с помощью структуры

struct rw_semaphore
, которая определена в файле
<asm/rwsem.h>
. Статически определенный семафор чтения-записи может быть создан с помощью функции

static DECLARE_RWSEM(name);

где

name
— это имя нового семафора.

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

init_rwsem(struct rw_semaphore *sem);

Все семафоры чтения-записи являются взаимоисключающими (mutex), т.е. их счетчик использования равен единице. Любое количество потоков чтения может одновременно удерживать блокировку чтения, если при этом нет ни одного потока записи. И наоборот, только один поток записи может удерживать блокировку, захваченную на запись, если нет ни одного потока чтения. Все семафоры чтения-записи используют непрерываемое состояние ожидания, поэтому существует только одна версия функции

down.
Рассмотрим следующий пример.

static DECLARE_RWSEM(mr_rwsem);

/* попытка захватить семафор для чтения */

down_read(&mr_rwsem);

/* критический участок (только чтение) ... */

/* освобождаем семафор */

up_read(&mr_rwsem);

/* ... * /

/* попытка захватить семафор на запись */

down_write(&mr_rwsem);

/* освобождаем семафор */

/* критический участок (чтение и запись) ... */

up write(&mr_rwsem);

Для семафоров есть реализации функций

down_read_trylock
и
down_write_trylock
. Каждая из них принимает один параметр — указатель на семафор чтения-записи. Обе функции возвращают ненулевое значение, если блокировка захвачена успешно, и нуль, если блокировка находится в состоянии конфликта. Следует быть внимательными — поведение этих функций противоположно поведению аналогичных функций для обычных семафоров, причем без всякой на то причины!

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

downgrade_writer
, которая автоматически превращает блокировку, захваченную на запись, в блокировку, захваченную на чтение.

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

Сравнение спин-блокировок и семафоров

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

Таблица 9.6. Что следует использовать: семафоры или спин-блокировки

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

Свадьба по приказу, или Моя непокорная княжна

Чернованова Валерия Михайловна
Любовные романы:
любовно-фантастические романы
5.57
рейтинг книги
Свадьба по приказу, или Моя непокорная княжна

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Отец моего жениха

Салах Алайна
Любовные романы:
современные любовные романы
7.79
рейтинг книги
Отец моего жениха

Вадбольский

Никитин Юрий Александрович
1. Вадбольский
Фантастика:
попаданцы
5.00
рейтинг книги
Вадбольский

Бастард Императора. Том 7

Орлов Андрей Юрьевич
7. Бастард Императора
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард Императора. Том 7

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

В зоне особого внимания

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

Таня Гроттер и магический контрабас

Емец Дмитрий Александрович
1. Таня Гроттер
Фантастика:
фэнтези
8.52
рейтинг книги
Таня Гроттер и магический контрабас

Бастард Императора. Том 2

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

Кодекс Крови. Книга ХI

Борзых М.
11. РОС: Кодекс Крови
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Кодекс Крови. Книга ХI

Третий

INDIGO
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий

Возвышение Меркурия. Книга 16

Кронос Александр
16. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 16

Идеальный мир для Лекаря 9

Сапфир Олег
9. Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
6.00
рейтинг книги
Идеальный мир для Лекаря 9

Потусторонний. Книга 1

Погуляй Юрий Александрович
1. Господин Артемьев
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Потусторонний. Книга 1