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

на главную

Жанры

Разработка ядра 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. Что следует использовать: семафоры или спин-блокировки

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

Месть Пламенных

Дмитриева Ольга
6. Пламенная
Фантастика:
фэнтези
6.00
рейтинг книги
Месть Пламенных

Королевская Академия Магии. Неестественный Отбор

Самсонова Наталья
Любовные романы:
любовно-фантастические романы
8.22
рейтинг книги
Королевская Академия Магии. Неестественный Отбор

Имперец. Том 3

Романов Михаил Яковлевич
2. Имперец
Фантастика:
боевая фантастика
попаданцы
альтернативная история
7.43
рейтинг книги
Имперец. Том 3

Бракованная невеста. Академия драконов

Милославская Анастасия
Фантастика:
фэнтези
сказочная фантастика
5.00
рейтинг книги
Бракованная невеста. Академия драконов

Темный Лекарь 7

Токсик Саша
7. Темный Лекарь
Фантастика:
попаданцы
аниме
фэнтези
5.75
рейтинг книги
Темный Лекарь 7

Кодекс Охотника. Книга XIII

Винокуров Юрий
13. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
7.50
рейтинг книги
Кодекс Охотника. Книга XIII

Низший - Инфериор. Компиляция. Книги 1-19

Михайлов Дем Алексеевич
Фантастика 2023. Компиляция
Фантастика:
боевая фантастика
5.00
рейтинг книги
Низший - Инфериор. Компиляция. Книги 1-19

Магия чистых душ 2

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.56
рейтинг книги
Магия чистых душ 2

Курсант: Назад в СССР 11

Дамиров Рафаэль
11. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 11

Назад в СССР 5

Дамиров Рафаэль
5. Курсант
Фантастика:
попаданцы
альтернативная история
6.64
рейтинг книги
Назад в СССР 5

Черный Маг Императора 7 (CИ)

Герда Александр
7. Черный маг императора
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 7 (CИ)

Машенька и опер Медведев

Рам Янка
1. Накосячившие опера
Любовные романы:
современные любовные романы
6.40
рейтинг книги
Машенька и опер Медведев

Отмороженный 4.0

Гарцевич Евгений Александрович
4. Отмороженный
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Отмороженный 4.0

Покоривший СТЕНУ 6: Пламя внутри

Мантикор Артемис
6. Покоривший СТЕНУ
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Покоривший СТЕНУ 6: Пламя внутри