Разработка ядра Linux
Шрифт:
Требование | Рекомендуемый тип блокировки |
---|---|
Блокировка с малыми накладными затратами (low overhead) | Спин-блокировки более предпочтительны |
Малое время удержания блокировки | Спин-блокировки более предпочтительны |
Длительное время удержания блокировки | Семафоры более предпочтительны |
Необходимо использовать блокировку в контексте прерывания | Необходима спин-блокировка |
Необходимо переходить в состояние
| Необходимо использовать семафоры |
Условные переменные
Условные переменные (conditional variable, completion variable) — простое средство синхронизации между двумя заданиями, которые работают в режиме ядра, когда необходимо, чтобы одно задание послало сигнал другому о том, что произошло некоторое событие. При этом одно задание ожидает на условной переменной, пока другое задание не выполнит некоторую работу. Когда другое задание завершит выполнение своей работы, оно использует условную переменную для того, чтобы возвратить к выполнению все ожидающие на ней задания. Если это кажется похожим на работу семафора, то именно так оно и есть, идея та же. В действительности, условные переменные просто обеспечивают простое решение проблемы, для которой в других ситуациях используются семафоры. Например, в системном вызове
Условные переменные представляются с помощью структуры
Статически условная переменная может быть создана с помощью макроса
Динамически созданная условная переменная может быть инициализирована с помощью функции
Задание, которое должно ожидать на условной переменной, вызывает функцию
Таблица. 9.7. Методы работы с условными переменными
Метод | Описание |
---|---|
init_completion(struct completion*) | Инициализация динамически созданной условной переменной в заданной области памяти |
wait_for_completion(struct completion*) | Ожидание сигнала на указанной условной переменной |
complete(struct completion*) | Отправка сигнала всем ожидающим заданиям и возвращение их к выполнению |
Для примеров использования условных переменных смотрите файлы
BKL: Большая блокировка ядра
Добро пожаловать к "рыжему пасынку" ядра. Большая блокировка ядра (Big Kernel Lock, BKL) — это глобальная спин-блокировка, которая была создана специально для того, чтобы облегчить переход от первоначальной реализации SMP в операционной системе Linux к мелкоструктурным блокировкам. Блокировка BKL имеет следующие интересные свойства.
• Во
• Блокировка BKL рекурсивна. Один процесс может захватывать эту блокировку несколько раз подряд, и это не приведет к самоблокировке, как в случае обычных спин-блокировок.
• Блокировка BKL может использоваться только в контексте процесса.
• Блокировка BKL — это от лукавого.
Рассмотренные свойства дали возможность упростить переход от ядер серии 2.0 к серии 2.2. Когда в ядро 2.0 была введена поддержка SMP, только одно задание могло выполняться в режиме ядра в любой момент времени (конечно, сейчас ядро распараллелено очень хорошо — пройден огромный путь). Целью создания ядра серии 2.2 было обеспечение возможности параллельного выполнения кода ядра на нескольких процессорах. Блокировка BKL была введена для того, чтобы упростить переход к мелкоструктурным блокировкам. В те времена она оказала большую помощь, а сегодня она приводит к ухудшению масштабируемости [51] .
51
Хотя, может быть, она и не такая страшная, какой ее иногда пытаются представить, вес же некоторые люди считают ее "воплощением дьявола" в ядре.
Использовать блокировку BKL не рекомендуется. На самом деле, новый код никогда не должен использовать BKL. Однако эта блокировка все еще достаточно интенсивно используется в некоторых частях ядра. Поэтому важно понимать особенности большой блокировки ядра и интерфейса к ней. Блокировка BKL ведет себя, как обычная спин-блокировка, за исключением тех особенностей, которые были рассмотрены выше. Функция
Когда эта блокировка захвачена, происходит запрещение преемптивности. Для ядер, скомпилированных под однопроцессорную машину, код BKL на самом деле не выполняет никаких блокировок. В табл. 9.8 приведен полный список функций работы с BKL.
Таблица 9.8. Функции работы с большой блокировкой ядра