Отладка атомарных операций
Начиная с серии 2.5 в ядре появилась отличная инфраструктура для определения всех типов нарушения атомарности. Вспомните из главы 8, "Введение в синхронизацию выполнения кода ядра", что атомарность означает неделимое выполнение, то есть код выполняется без перерыва до завершения, или не завершается вообще. Код, который удерживает спин-блокировку, или выполняется при запрещенной преемптивности ядра, является атомарным. Во время атомарного выполнения нельзя переходить в состояние ожидания. Ожидание при удерживаемой спин-блокировке — один из вариантов взаимоблокировки.
Благодаря свойствам преемптивности, ядро имеет глобальный счетчик преемптивности. Ядро может быть настроено так, что, если выполняется переход в состояние ожидания, или даже выполняется код, который потенциально может переходить в состояние ожидания при выполнении атомарной операции, то ядро выводит предупреждающее сообщение и обратную трассировку. Потенциальные ошибки, которые детектируются таким образом, включают вызов функции schedule () при удерживаемой блокировке, выполнение блокирующего выделения памяти при удерживаемой блокировке, или переход в состояние ожидания при удерживаемой ссылке на данные, связанные с процессором. Эта отладочная инфраструктура может обнаружить очень много ошибок и ее очень рекомендуется использовать.
Следующие конфигурационные параметры позволяют полностью использовать данную возможность.
CONFIG_PREEMPT=y
CONFIG_DEBUG_KERNEL=y
CONFIG_KALLSYMS=y
CONFIG_SPINLOCK_SLEEP=y
Генерация ошибок и выдача информации
Существует несколько подпрограмм ядра, которые позволяют легко сигнализировать о наличии дефектов кода, обеспечивать объявления об ошибках и выводить необходимую информацию. Две наиболее часто используемые — это BUG()
и BUG_ON()
. При вызове эти функции создают ситуацию oops
, которая проявляется в выводе обратной трассировки стека ядра и сообщения об ошибке. Каким образом эти вызовы генерируют ситуацию oops зависит от аппаратной платформы. Для большинства аппаратных платформ вызовы BUG()
и BUG_ON()
определяются как некоторая недопустимая машинная команда, которая приводит к выводу желаемого сообщения oops
.
Обычно эти вызовы используются в качестве объявления о наличие ошибки (assertion), чтобы сигнализировать о ситуации, которая не должна произойти.
if (bad_thing)
BUG();
Или даже так.
BUG_ON(bad_thing);
О более критичной ошибке можно сигнализировать с помощью функции panic()
. Функция panic()
печатает сообщение об ошибке и останавливает ядро. Ясно, что эту функцию следует использовать только в самой плохой ситуации.
if (terrible_thing)
panic("foo is %ld!\n", foo);
Иногда необходимо просто вывести на консоль трассировку стека, чтобы облегчить отладку. В этих случаях используется функция dump_stack()
. Эта функция отображает на консоль содержимое регистров процессора и обратную трассировку вызовов функций.
if (!debug_check) {
printk(KERN_DEBUG "выдать некоторую информацию...\n");
dump_stack();
}
Использование магической клавиши SysRq
, которую можно активизировать с помощью конфигурационного параметра CONFIG_MAGIC_SYSRQ
на этапе компиляции, часто позволяет значительно облегчить жизнь. Клавиша SysRq
является стандартной на многих клавиатурах. Для аппаратных платформ i386 и PPC ей соответствует комбинация клавиш ALT-PrintScreen
. Если указанный конфигурационный параметр активизирован, то специальные комбинации клавиш позволяют взаимодействовать с ядром независимо от того, чем ядро в данный момент нанимается. Это в свою очередь позволяет выполнять некоторые полезные операции даже на неработоспособной системе.
В дополнение к конфигурационному параметру существует вызов sysctl
для включения и выключения этого свойства.
echo 1 > /proc/sys/kernel/sysrq
Список возможных комбинаций клавиш можно получить с консоли путем нажатия комбинации клавиш SysRq-h
. Комбинация клавиш SysRq
-s выполняет синхронизацию не сохраненных буферов файловых систем на диск, комбинация SysRq-u
размонтирует все файловые системы, a SysRq-b
— перегружает машину. Последовательное использование этих комбинаций клавиш позволяет более безопасно перегрузить машину, которая зависла, чем простое нажатие кнопки reset
.
Читать дальше