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

на главную

Жанры

Разработка ядра Linux
Шрифт:

Вспомним, что два тасклета (tasklet) одного типа не могут выполняться параллельно. Поэтому нет необходимости защищать данные, которые используются только тасклетами одного типа.

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

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

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

Спин-блокировки чтения-записи

Иногда в соответствии с целью использования блокировок их можно разделить два типа — блокировки чтения (reader lock) и блокировки записи (writer lock). Рассмотрим некоторый список, который может обновляться и в котором может выполняться поиск. Когда список обновляется (в него осуществляется запись), никакой другой код не может параллельно осуществлять запись или чтение этого списка. Запись означает исключительный доступ. С другой стороны, если в списке выполняется поиск (чтение информации), важно только, чтобы никто другой не выполнял записи в список. Работа со списком заданий в системе (как обсуждалось в главе 3, "Управление процессами") аналогична только что описанной ситуации. Не удивительно, что список заданий в системе защищен с помощью спин-блокировки чтения- записи (reader-writer spin lock).

Если работа со структурой данных может быть четко разделена на этапы чтения/записи, как в только что рассмотренном случае, то имеет смысл использовать механизмы блокировок с аналогичной семантикой. Для таких ситуаций операционная система Linux предоставляет спин-блокировки чтения-записи. Спин-блокировки чтения-записи обеспечивают два варианта блокировки. Один или больше потоков выполнения, которые одновременно выполняют операции считывания, могут удерживать такую блокировку. Блокировка на запись, наоборот, может удерживаться в любой момент времени только одним потоком, осуществляющим запись, и никаких параллельных считываний не разрешается. Блокировки чтения-записи иногда также называются соответственно shared/exclusive (общая/ исключающая) или concurrent/exclusive (параллельная/исключающая).

Инициализировать блокировку для чтения-записи можно с помощью следующего программного кода.

rwlock_t mr_rwlock = RW_LOCK_UNLOCKED;

Следующий код осуществляет считывание.

read_lock(&mr_rwlock);

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

read unlock(&mr_rwlock);

И наконец, показанный ниже код осуществляет запись.

write_lock(&mr_rwlock);

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

write_unlock{&mr_rwlock);

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

Заметим, что блокировку, захваченную для чтения, нельзя "повышать" до блокировки, захваченной для записи. В следующем коде

read_lock(&mr_rwlock);

write_lock(&mr_rwlock);

возникнет самоблокировка, так как при захвате блокировки на запись будет выполняться периодическая проверка, пока все потоки, которые захватили блокировку для чтения, ее не освободят; это касается и текущего потока. Если в каком-либо месте будет необходима запись, то нужно сразу же захватывать блокировку для записи. Если в вашем коде нет четкого разделения на код, который осуществляет считывание, и код, который осуществляет запись, то нет необходимости использовать блокировки чтения- записи. В таком случае оптимальным будет использование обычных спин-блокировок.

Несколько потоков чтения безопасно могут удерживать одну и ту же блокировку чтения-записи. На самом деле один поток также может безопасно рекурсивно захватывать одну и ту же блокировку для чтения. Это позволяет выполнить полезную и часто используемую оптимизацию. Если в обработчиках прерываний осуществляется только чтение и не выполняется запись, то можно "смешивать" использование блокировок с запрещением прерываний и без запрещения. Для защиты данных при чтении можно использовать функцию

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

Таблица 9.4. Список функций работы со спин-блокировками чтения-записи

Функция Описание
read_lock
Захватить указанную блокировку на чтение
read_lock_irq
Запретить прерывания на локальном процессоре и захватить указанную блокировку на чтение
read_lock_irqsave
Сохранить состояние системы прерываний на текущем процессоре, запретить прерывания на локальном процессоре и захватить указанную блокировку на чтение
read_unlock
Освободить указанную блокировку, захваченную для чтения
read_unlock_irq
Освободить указанную блокировку, захваченную для чтения, и разрешить прерывания на локальном процессоре
read_unlock_irqrestore
Освободить указанную блокировку, захваченную для чтения, и восстановить состояние системы прерываний в указанное значение
write_lock
Захватить заданную блокировку на запись
write_lock_irq
Запретить прерывания на локальном процессоре и захватить указанную блокировку на запись
write_lock_irqsave
Сохранить состояние системы прерываний на текущем процессоре, запретить прерывания на локальном процессоре и захватить указанную блокировку на запись
write_unlock
Освободить указанную блокировку, захваченную для записи
write_unlock_irq
Освободить указанную блокировку, захваченную для записи, и разрешить прерывания на локальном процессоре
write_unlock_irqrestore
Освободить указанную блокировку, захваченную для записи, и восстановить состояние системы прерываний в указанное значение
write_trylock
Выполнить попытку захватить заданную блокировку на запись и в случае неудачи возвратить ненулевое значение
rw_lock_init
Инициализировать объект типа
rwlock_t
в заданной области памяти
rw_is_locked
Возвратить ненулевое значение, если указанная блокировка захвачена, иначе возвратить нуль

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

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

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

Измена. Я отомщу тебе, предатель

Вин Аманда
1. Измены
Любовные романы:
современные любовные романы
5.75
рейтинг книги
Измена. Я отомщу тебе, предатель

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад

Мимик нового Мира 6

Северный Лис
5. Мимик!
Фантастика:
юмористическая фантастика
попаданцы
рпг
5.00
рейтинг книги
Мимик нового Мира 6

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

Сапфир Олег
2. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 2

Начальник милиции

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

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

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

Темный Патриарх Светлого Рода 4

Лисицин Евгений
4. Темный Патриарх Светлого Рода
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Темный Патриарх Светлого Рода 4

Стрелок

Астахов Евгений Евгеньевич
5. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Стрелок

На границе империй. Том 6

INDIGO
6. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.31
рейтинг книги
На границе империй. Том 6

Архил…? Книга 3

Кожевников Павел
3. Архил...?
Фантастика:
фэнтези
попаданцы
альтернативная история
7.00
рейтинг книги
Архил…? Книга 3

Доктора вызывали? или Трудовые будни попаданки

Марей Соня
Фантастика:
юмористическая фантастика
попаданцы
5.00
рейтинг книги
Доктора вызывали? или Трудовые будни попаданки

Лорд Системы 11

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

Черный Маг Императора 5

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

Последний попаданец 2

Зубов Константин
2. Последний попаданец
Фантастика:
юмористическая фантастика
попаданцы
рпг
7.50
рейтинг книги
Последний попаданец 2