Linux Device Drivers 3 / Драйверы устройств Линукс (третье издание): 4.2. Отладка через печать

Оглавление
← →
Английский оригинал Перевод на русский

Сожалеем, но текст оригинала доступен только зарегистрированным пользователям.

Отладка через печать

hardorsoft 19.11.10 в 11:54

0

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

hardorsoft 19.11.10 в 11:55

0

4.2.1. printk

ximen 08.11.10 в 08:58

0

Мы использовали функцию printk в предыдущих главах с упрощающим предположением, что она работает как printf. Теперь пришло время познакомиться с некоторыми отличиями.

hardorsoft 19.11.10 в 11:55

0

Одним из отличий является то, что printk позволяет классифицировать сообщения в зависимости от их серьёзности, связывая разные уровни логирования (loglevels) или приоритеты, с сообщениями. Вы обычно указываете уровень логирования макросом. Например, KERN_INFO, который мы видели предшествующим чему-либо в приведённых раннее вызовах печати, является одним из возможных уровней логирования сообщений. Макрос уровня логирования заменяется на строку, которая объединяется с текстом сообщения во время компиляции; вот почему в следующих примерах нет запятой между приоритетом и строкой форматирования. Вот два примера команд printk, отладочное сообщение и критическое сообщение:

hardorsoft 19.11.10 в 11:55

0

<code>
printk(KERN_DEBUG "Here I am: %s:%i\n", __FILE__, __LINE__);
printk(KERN_CRIT "I'm trashed; giving up on %p\n", ptr);
</code>

ximen 08.11.10 в 08:59

0

Есть восемь возможных строк уровня логирования, определённых в заголовке <linux></linux>kernel.h>; мы перечисляем их в порядке убывания серьёзности:

hardorsoft 19.11.10 в 11:56

0

KERN_EMERG

ximen 08.11.10 в 08:59

0

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

hardorsoft 19.11.10 в 11:58

0

KERN_ALERT

ximen 08.11.10 в 08:59

0

Ситуации, требующей немедленных действий.

hardorsoft 19.11.10 в 11:58

0

KERN_CRIT

ximen 08.11.10 в 08:59

0

Критические условия, часто связанные с серьёзными аппаратными или программными сбоями.

hardorsoft 19.11.10 в 11:58

0

KERN_ERR

ximen 08.11.10 в 08:59

0

Используется, чтобы сообщить об ошибочных условиях; драйверы устройств часто используют KERN_ERR для сообщения об аппаратных проблемах.

hardorsoft 19.11.10 в 11:58

0

KERN_WARNING

ximen 08.11.10 в 08:59

0

Предупреждения о проблемных ситуациях, которые сами по себе не создают серьёзных проблем с системой.

hardorsoft 19.11.10 в 11:59

0

KERN_NOTICE

ximen 08.11.10 в 08:59

0

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

hardorsoft 19.11.10 в 11:59

0

KERN_INFO

ximen 08.11.10 в 08:59

0

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

hardorsoft 19.11.10 в 11:59

0

KERN_DEBUG

ximen 08.11.10 в 08:58

0

Используется для отладочных сообщений.

hardorsoft 19.11.10 в 11:59

0

Каждая строка (в макроподстановках) представляет собой целое число в угловых скобках. Целые числа в диапазоне от 0 до 7, чем меньше величина, тем больше приоритет.

hardorsoft 19.11.10 в 11:59

0

Вызов printk без заданного приоритета использует DEFAULT_MESSAGE_LOGLEVEL, определённый в kernel/printk.c как целое число. В ядре версии 2.6.10, DEFAULT_MESSAGE_LOGLEVEL является KERN_WARNING, но это, как известно, менялось в прошлом.

hardorsoft 19.11.10 в 11:59

0

На основании уровня логирования ядро может печатать сообщения в текущей консоли, будь то текстовый терминал, последовательный порт, или параллельный принтер. Если приоритет меньше целой переменной console_loglevel, сообщение будет доставлено на консоль по одной строке за раз (не посылается ничего, пока не получен завершающий символ "новая строка"). Если в системе работают и klogd и syslogd, сообщения ядра добавляются в /var/log/messages (или другой, в зависимости от вашей конфигурации syslogd), независимо от console_loglevel. Если klogd не работает, сообщение не дойдёт до пространства пользователя, пока вы не прочитаете /proc/kmsg (что часто проще всего сделать командой dmesg). При использовании klogd вы должны помнить, что он не сохраняет одинаковые следующие друг за другом строки; он сохраняет только первую такую линию, а позднее - количество полученных повторов.

hardorsoft 19.11.10 в 12:00

0

Переменная console_loglevel инициализируется с DEFAULT_CONSOLE_LOGLEVEL и может быть изменена с помощью системного вызова sys_syslog. Один из способов изменить это - задать значение ключом -c при вызове klogd, как указано в справке klogd. Обратите внимание, что для изменения текущего значения, вы должны сначала убить klogd, а затем перезапустить его с опцией -c. Кроме того, вы можете написать программу для изменения уровня логирования консоли. Вы найдёте вариант такой программы в misc-progs/setlevel.c в исходных файлах, находящихся на FTP сайте O'Reilly. Новый уровень определяется как целое число между 1 и 8, включительно. Если он установлен в 1, консоли достигают только сообщения уровня 0 (KERN_EMERG), если он установлен в 8, отображаются все сообщения, включая отладочные.

hardorsoft 19.11.10 в 12:00

0

Также можно читать и модифицировать уровень логирования консоли с помощью текстового файла /proc/sys/kernel/printk. Файл содержит четыре целых величины: текущий уровень логирования, уровень по умолчанию для сообщений, которые не имеют явно заданного уровня логирования, минимально разрешённый уровень логирования и уровень логирования по умолчанию во время загрузки. Запись одного значения в этот файл изменяет текущий уровень логирования на это значение; так, например, вы можете распорядиться, чтобы все сообщения ядра появлялись в консоли, простым вводом:

hardorsoft 19.11.10 в 12:00

0

# echo 8 > /proc/sys/kernel/printk

hardorsoft 19.11.10 в 12:00

0

Сейчас должно быть понятно, почему пример hello.c имел маркеры KERN_ALERT; они применялись для уверенности, что сообщение появится в консоли.

hardorsoft 19.11.10 в 12:00

0

Перенаправление сообщений консоли

hardorsoft 19.11.10 в 12:01

0

Linux обеспечивает определённую гибкость в политиках консольного логирования, позволяя отправлять сообщения на заданную виртуальную консоль (если ваша консоль живёт на текстовом экране). По умолчанию, "консолью" является текущий виртуальный терминал. Чтобы выбрать для приёма сообщений другой виртуальный терминал, вы можете на любом консольном устройстве вызвать ioctl(TIOCLINUX). Следующая программа, setconsole, может быть использована для выбора консоли, получающей сообщения ядра; она должна быть запущена суперпользователем и находиться в каталоге misc-progs.

hardorsoft 19.11.10 в 12:01

0

Ниже приводится программа в полном объёме. Вы должны вызывать её с одним аргументом, указывающим номер консоли, которая будет получать сообщения.

hardorsoft 19.11.10 в 12:01

0

<pre>
int main(int argc, char **argv)
{
char bytes[2] = {11,0}; /* 11 -- номер команды TIOCLINUX */
if (argc= =2) bytes[1] = atoi(argv[1]); /* выбранная консоль */
else {
fprintf(stderr, "%s: need a single arg\n",argv[0]); exit(1);
}
if (ioctl(STDIN_FILENO, TIOCLINUX, bytes)&lt;0) { /* использовать stdin */
fprintf(stderr,"%s: ioctl(stdin, TIOCLINUX): %s\n",
argv[0], strerror(errno));
exit(1);
}
exit(0);
}
</pre>

ximen 08.11.10 в 09:00

0

setconsole использует специальную команду ioctl TIOCLINUX, которая реализует особые функции Linux. Для использования TIOCLINUX вы передаёте аргумент, который является указателем на массив байтов. Первый байт массива является числом, которое определяет запрошенную подкоманду, а следующий байт зависит от подкоманды. В setconsole используется подкоманда 11, а следующий байт (хранимый в bytes[1]) идентифицирует виртуальную консоль. Полное описание TIOCLINUX может быть найдено в исходных текстах ядра в drivers/char/tty_io.c.

hardorsoft 19.11.10 в 12:01

0

Как получить сообщения из лога

hardorsoft 19.11.10 в 12:01

0

Функция printk записывает сообщения в круговой буфер размером __LOG_BUF_LEN байт: значение от 4 Кб до 1 Мб выбирается при конфигурации ядра. Эта функция затем будит любой процесс, который ожидает сообщений, то есть любой процесс, который является заснувшим при вызове системного вызова syslog или при чтении /proc/kmsg. Эти два интерфейса движка логирования почти эквивалентны, но учтите, что чтение /proc/kmsg забирает данные из буфера журнала, а системный вызов syslog может произвольно возвращать данные протокола, оставляя их для других процессов. В общем, чтение файла /proc проще и является поведением по умолчанию для klogd. Чтобы взглянуть на содержание буфера без сброса его на диск, может быть использована команда dmesg; на деле команда возвращает в stdout всё содержимое буфера, независимо от того, читался ли он до этого.

hardorsoft 19.11.10 в 12:01

0

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

hardorsoft 19.11.10 в 12:02

0

Если круговой буфер заполнится, printk вернётся в начало и начнёт добавлять новые данные с начала буфера, перезаписывая старые данные. Таким образом, процесс протоколирования теряет старые данные. Эта проблема незначительна по сравнению с преимуществами использования кругового буфера. Например, циклический буфер позволяет системе работать даже без процесса протоколирования, минимизируя потерю памяти и перезаписывая старые данные, которые никто не прочитает. Ещё одна особенность подхода Linux для обмена сообщениями, это то, что printk может быть вызвана из любого места, даже из обработчика прерываний, без ограничения на размер распечатываемых данных. Единственным недостатком является возможность потери некоторых данных.

hardorsoft 19.11.10 в 12:02

0

Если процесс klogd запущен, он получает сообщения ядра и передаёт их syslogd, который, в свою очередь, проверяет /etc/syslog.conf, чтобы выяснить, как с ними поступать. syslogd делает различия между сообщениями в соответствии с видом приложения и приоритетом; допустимые значения видов и приоритетов определены в заголовочном файле <sys></sys>syslog.h&gt;. Сообщения ядра протоколируются со значением типа LOG_KERN и соответствующим ему приоритетом, используемым в printk (например, LOG_ERR используется для сообщений KERN_ERR). Если klogd не работает, данные остаются в круговом буфере, пока кто-то не прочитает их или буфер не переполнится.

hardorsoft 19.11.10 в 12:02

0

Если вы хотите избежать затирания системного лога мониторинговыми сообщениями от вашего драйвера, вы можете либо указать опцию -f (файл) для klogd, чтобы поручить ему сохранять сообщения в заданный файл, или изменить /etc/syslog.conf в соответствии с вашими требованиями. Ещё одна возможность использовать метод решения "в лоб": убить klogd и многословно печатать сообщения на неиспользуемых виртуальных терминалах или дать команду cat /proc/kmsg из неиспользуемого xterm.

hardorsoft 19.11.10 в 12:03

0

(* Например, используйте setlevel 8; setconsole 10, чтобы установить терминал 10 для отображения сообщений.)

hardorsoft 19.11.10 в 12:03

0

Включение и выключение сообщений

hardorsoft 19.11.10 в 12:04

0

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

hardorsoft 19.11.10 в 12:04

0

Здесь мы покажем один из способов кодирования вызовов printk так, что вы сможете включать и выключать их индивидуально или глобально; техника зависит от определения макроса, который разрешает вызов printk (или printf), когда вы хотите, чтобы:

hardorsoft 19.11.10 в 12:04

0

Каждый оператор печати мог быть включен или отключен удалением или добавлением одной буквы к имени макроса.

hardorsoft 19.11.10 в 12:04

0

Все сообщения могли быть отключены сразу изменением значения переменной CFLAGS перед компиляцией.

hardorsoft 19.11.10 в 12:05

0

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

hardorsoft 19.11.10 в 12:05

0

Эти возможности реализует следующий фрагмент кода, взятый прямо из заголовка scull.h:

hardorsoft 19.11.10 в 12:05

0

#undef PDEBUG /* уберём определение на всякий случай */
#ifdef SCULL_DEBUG
# ifdef __KERNEL__
    /* используется, если включена отладка и пространство ядра */
# define PDEBUG(fmt, args...) printk( KERN_DEBUG "scull: " fmt, ## args)
# else
    /* используется для пользовательского пространства */
# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
# endif
#else
# define PDEBUG(fmt, args...) /* не отлаживаемся: ничего */
#endif
 
#undef PDEBUGG
#define PDEBUGG(fmt, args...) /* ничего: это пустышка */

hardorsoft 19.11.10 в 12:05

0
Минутку...

Следующая страница →