Книга: Разработка ядра Linux
BKL: Большая блокировка ядра
BKL: Большая блокировка ядра
Добро пожаловать к "рыжему пасынку" ядра. Большая блокировка ядра (Big Kernel Lock, BKL) — это глобальная спин-блокировка, которая была создана специально для того, чтобы облегчить переход от первоначальной реализации SMP в операционной системе Linux к мелкоструктурным блокировкам. Блокировка BKL имеет следующие интересные свойства.
• Во время удержания BKL можно переходить в состояние ожидания. Блокировка автоматически освобождается, когда задание переходит в состояние ожидания, и снова захватывается, когда задание планируется на выполнение. Конечно, это не означает, что безопасно переходить в состояние ожидания при удержании BKL, просто это можно делать и это не приведет к взаимоблокировке.
• Блокировка BKL рекурсивна. Один процесс может захватывать эту блокировку несколько раз подряд, и это не приведет к самоблокировке, как в случае обычных спин-блокировок.
• Блокировка BKL может использоваться только в контексте процесса.
• Блокировка BKL — это от лукавого.
Рассмотренные свойства дали возможность упростить переход от ядер серии 2.0 к серии 2.2. Когда в ядро 2.0 была введена поддержка SMP, только одно задание могло выполняться в режиме ядра в любой момент времени (конечно, сейчас ядро распараллелено очень хорошо — пройден огромный путь). Целью создания ядра серии 2.2 было обеспечение возможности параллельного выполнения кода ядра на нескольких процессорах. Блокировка BKL была введена для того, чтобы упростить переход к мелкоструктурным блокировкам. В те времена она оказала большую помощь, а сегодня она приводит к ухудшению масштабируемости[51].
Использовать блокировку BKL не рекомендуется. На самом деле, новый код никогда не должен использовать BKL. Однако эта блокировка все еще достаточно интенсивно используется в некоторых частях ядра. Поэтому важно понимать особенности большой блокировки ядра и интерфейса к ней. Блокировка BKL ведет себя, как обычная спин-блокировка, за исключением тех особенностей, которые были рассмотрены выше. Функция lock_kernel()
позволяет захватить блокировку, а функция unlock_kernel()
— освободить блокировку. Каждый поток выполнения может рекурсивно захватывать эту блокировку, но после этого необходимо столько же раз вызвать функцию unlock_kernel()
. При последнем вызове функции освобождения блокировки блокировка будет освобождена. Функция kernel_locked()
возвращает ненулевое значение, если блокировка в данный момент захвачена, в противном случае возвращается нуль. Эти интерфейсы определены в файле <linux/smp_lock.h>
. Рассмотрим простой пример использования этой блокировки.
lock_kernel();
/*
* Критический раздел, который синхронизирован со всеми пользователями
* блокировки BKL...
* Заметим, что здесь можно безопасно переходить в состояние ожидания
* и блокировка будет прозрачным образом освобождаться.
* После перепланирования блокировка будет прозрачным образом снова
* захватываться.
* Это гарантирует, что не возникнет состояния взаимоблокировки,
* но все-таки лучше не переходить в состояние ожидания,
* если необходимо гарантировать защиту данных!
*/
unlock_kernel();
Когда эта блокировка захвачена, происходит запрещение преемптивности. Для ядер, скомпилированных под однопроцессорную машину, код BKL на самом деле не выполняет никаких блокировок. В табл. 9.8 приведен полный список функций работы с BKL.
Таблица 9.8. Функции работы с большой блокировкой ядра
Функция | Описание |
---|---|
lock_kernel() |
Захватить блокировку BKL |
unlock_kernel() |
Освободить блокировку BKL |
kernel_locked() |
Возвратить ненулевое значение, если блокировка захвачена, и нуль- в противном случае |
Одна из самых главных проблем, связанных с большой блокировкой ядра, — как определить, что защищается с помощью данной блокировки. Часто блокировка BKL ассоциируется с кодом (например, она "синхронизирует вызовы функции foo()
"), а не с данными ("защита структуры foo
"). Это приводит к тому, что заменить BKL обычными спин-блокировками бывает сложно, потому что нелегко определить, что же все-таки необходимо блокировать. На самом деле, подобная замена еще более сложна, так как необходимо учитывать все взаимоотношения между всеми участками кода, которые используют эту блокировку.
- Атомарные операции
- Спин-блокировки
- Спин-блокировки чтения-записи
- Семафоры
- Семафоры чтения-записи
- Сравнение спин-блокировок и семафоров
- Условные переменные
- BKL: Большая блокировка ядра
- Секвентные блокировки
- Средства запрещения преемптивности
- Барьеры и порядок выполнения
- Резюмирование по синхронизации
- Статистика по блокировкам
- 1.1 Режимы ядра и пользователя Windows
- Большая книга директора магазина 2.0. Новые технологии
- 3.8. Обновление ядра
- 3.8.2. Обновление ядра из RPM-пакета
- 3.8.3. Компиляция ядра
- 8.6.1. Блокировка приема спама
- 8.6.2. Блокировка пересылки спама
- 14.1.8. Патчинг ядра
- 14.2.2. Блокировка POSIX: fcntl() и lockf()
- 14.11.1. Параметры ядра
- Глава 7 Большая возможность