Можно пользоваться практически всеми командами программы gdb для чтения информации. Например, чтобы напечатать значение переменной можно воспользоваться командой.
p global_variable
Для того, чтобы дизассемблировать код функции можно выполнить следующую команду.
disassemble function
Если ядро было скомпилировано с указанием флага -g (необходимо добавить -g
к значению переменной CFLAGS
в файле Makefile
ядра), то отладчик gdb сможет выдавать больше информации. Например, можно выводить дампы структур данных и разыменовывать указатели. При этом также получается ядро значительно большего размера, поэтому для обычной работы не следует компилировать ядро с отладочной информацией.
К сожалению, на этом заканчиваются возможности использования отладчика gdb. С его помощью никак нельзя изменять данные ядра. Нет возможности пошагово выполнять код ядра, или устанавливать точки остановки (breakpoint). Невозможность изменять структуры данных ядра — это большой недостаток. Хотя очень полезно иметь возможность дизассемблировать код функций, еще более полезной была бы возможность изменять структуры данных.
Отладчик kgdb
Отладчик kgdb — это заплата ядра, которая позволяет с помощью отладчика gdb отлаживать ядро по линии последовательной передачи. Для этого требуется два компьютера. На первом выполняется ядро с заплатой kgdb. Второй компьютер используется для отладки ядра по линии последовательной передачи (нуль-модемный кабель, соединяющий две машины) с помощью gdb. Благодаря отладчику kgdb полностью доступен весь набор функций gdb: чтение и запись любых переменных, установка точек остановки, установка точек слежения (watch points), пошаговое исполнение и др.. Специальные версии kgdb даже позволяют вызывать функции.
Установка kgdb и линии последовательной передачи несколько сложная процедура, но если ее выполнить, то отладка ядра значительно упрощается. Заплата ядра также устанавливает большое количество документации в каталог Documentation/
, ее следует прочитать.
Несколько человек выполняют поддержку заплаты kgdb для различных аппаратных платформ и версий ядра. Поиск в Интернет — наилучший способ найти необходимую заплату для заданного ядра.
Отладчик kdb
Альтернативой kgdb является отладчик kdb. В отличие от kgdb отладчик kdb — не удаленный отладчик. Отладчик kdb — это заплата, которая сильно модифицирует ядро и позволяет выполнять отладку прямо на той же машине, где выполняется ядро. Кроме всего прочего поддерживается возможность изменения переменных, установки точек остановки и пошаговое выполнение. Выполнять отладку просто — необходимо нажать на консоли клавишу break
. При выводе сообщения oops переход в отладчик выполняется автоматически. Более подробная документация доступна в каталоге Documentation/kdb
после применения заплаты. Заплата kdb доступна в Интернет по адресу http://oss.sgi.com/
.
Исследование и тестирование системы
По мере того, как вы будете накапливать опыт в отладке ядра, у вас будет появляться все больше маленьких хитростей, которые помогают в исследовании и тестировании ядра для получения ответов на интересующие вопросы. Так как отладка ядра требует больших усилий, то каждый маленький совет, или хитрость может оказаться полезным. Рассмотрим несколько таких хитростей.
Использование идентификатора UID в качестве условия
Если разрабатываемый код связан с контекстом процесса, то иногда появляется возможность выполнить альтернативную реализацию не "ломая" существующий код. Это важно, если необходимо переписать важный системный вызов и при этом необходима полностью функционирующая система, на которой этот вызов нужно отладить. Например, допустим, что нужно переписать алгоритм работы системного вызова fork()
, который бы использовал некоторые новые возможности, которые уже существуют в ядре. Если сразу не получится все сделать так как надо, то будет очень тяжело отлаживать ядро, так как неработающий системный вызов fork()
скорее всего приведет к неработоспособности системы. Но как и всегда, есть надежда.
Часто безопасным будет сохранить старый алгоритм, а новую реализацию выполнить в другом месте. Этого можно достичь используя идентификатор пользователя (UID) в качестве условия того, какой алгоритм использовать.
if (current->uid != 7777) {
/* старый алгоритм ... */
} else {
/* новый алгоритм ... */
}
Все пользователи, кроме того, у которого идентификатор UID равен 7777 будут использовать старый алгоритм. Для тестирования нового алгоритма можно создать нового пользователя с идентификатором 7777. Это позволяет более просто оттестировать критические участки кода, связанные с выполнением процессов.
Использование условных переменных