Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Цилюрик О.И. Модули ядра Linux
Назад Вперед

Вывод диагностики модуля

Для диагностического вывода из модуля используем вызов printk(). Он настолько подобен по своим правилам и формату общеизвестному из пользовательского пространства printf(), что даже не требует дополнительного описания. Отметим только некоторые тонкие особенности printk() относительно printf():

Первому параметру может предшествовать (а может и не предшествовать) константа квалификатор, определяющая уровень сообщений. Определения констант для 8 уровней сообщений, записываемых в вызове printk() вы найдёте в файле /lib/modules/2.6.18-92.el5/build/include/linux/kernel.h:

#define KERN_EMERG "<0>" /* system is unusable */

#define KERN_ALERT "<1>" /* action must be taken immediately */

#define KERN_CRIT "<2>" /* critical conditions */

#define KERN_ERR "<3>" /* error conditions */

#define KERN_WARNING "<4>" /* warning conditions */

#define KERN_NOTICE "<5>" /* normal but significant condition */

#define KERN_INFO "<6>" /* informational */

#define KERN_DEBUG "<7>" /* debug-level messages */

Предшествующая константа не является отдельным параметром (не отделяется запятой), и (как видно из определений) представляет собой символьную строку определённого вида, которая конкатенируется с первым параметром (являющимся, в общем случае, форматной строкой). Если такая константа не записана, то устанавливается уровень вывода этого сообщения по умолчанию. Таким образом, следующие формы записи могут быть эквивалентны:

printk( KERN_WARNING "string" );

printk( "<4>" "string" );

printk( "<4>string" );

printk( "string" );

Вызов printk() не производит непосредственно вызов, а направляет вывод демону системного журнала, который уже перезаписывает полученную строку: а). на текстовую консоль и б). в системный журнал. При работе в графической системе X11, вывод printk() в терминал xterm не попадает, поэтому остаётся только в системном журнале. Это имеет, помимо прочего, тонкое следствие, которое часто упускается из виду: независимо от того, завершается или нет строка, формируемая printk(), переводом строки ('\n'), «решать» переводить или нет строку будет демон системного журнала (klogd или rsyslog), и разные демоны, похоже, решают это по-разному. Таким образом, попытка конкатенации строк:

printk( "string1" );

printk( " + string2" );

printk( " + string3\n" );

- в любом показанном варианте окажется неудачной: в системе 2.6.32 (rsyslog) будет выведено 3 строки, а в 2.6.18 (klogd) это будет единая строка: string1 + <4>string2 + <4>string3, но это наверняка не то, что вы намеревались получить... А что же делать, если нужно конкатенировать вывод в зависимости от условий? Нужно формировать весь нужный вывод в строку с помощью sprintf(), а потом выводить всю эту строку посредством printk() (это вообще хороший способ для модуля, чтобы не дёргать по много раз ядро и демон системного журнала многократными printk()).

Вывод системного журнала направляется, как уже сказано, и отображается в текстовой консоли, но не отображается в графических терминалах X11. Большинство нормальных разработчиков, по крайней мере при определённых обстоятельствах или в определённые периоды, ведут отработку модулей в X11, и иногда крайне удобно иметь возможность параллельно контролировать вывод на текстовой консоли (а иногда это и единственный способ видеть диагностику, когда она не успевает дойти до системного журнала перед гибелью системы). Всю оставшуюся часть этого раздела мы будем обсуждать, как удобнее это сделать, и как управлять всеми этими консолями, поэтому, если эти возможности вас не интересуют, эту часть можно спокойно опустить.

Вы всегда можете оперативно переключаться между графическим экраном X11 и несколькими (обычно 6, зависит от конфигурации) текстовыми консолями, делается это клавишной комбинацией: <Ctrl><Alt><Fi>, где Fi - «функциональная клавиша». Но вот распределение экранов по i может быть разным (в зависимости от способа конфигурации дистрибутива Linux), я встречал:

- в Fedora 12 : <Ctrl><Alt><F1> - X11, <Ctrl><Alt><F2>...<F7> - текстовые консоли;

- в CentOS 5.2 : <Ctrl><Alt><F1>...<F6> - текстовые консоли, <Ctrl><Alt><F7> - X11;

Большой неожиданностью может стать отсутствие вывода printk() в текстовую консоль. Но этот вывод обеспечивается демоном системного журнала, и он выводит только сообщения выше порога, установленного ему при запуске. Для снижения порога вывода диагностики демон системного журнала может быть придётся перезапустить с другими параметрами. В более старых дистрибутивах в качестве демонов логирования используются syslogd и klogd, проверить это можете:

$ ps -A | grep logd

4094 ? 00:00:00 syslogd

4097 ? 00:00:00 klogd

Нас, в данном случае, интересует klogd. В более свежих дистрибутивах может использоваться один демон rsyslogd, берущий на себя функции и syslogd и klogd:

$ ps -A | grep logd

1227 ? 00:00:00 rsyslogd

С какими параметрами предстоит перезапускать демон журнала зависит, естественно, от вида демона... Детальную информацию вы можете получить командами (и, соответственно, точно так же и для варианта klogd):

$ man rsyslogd

...

$ rsyslogd --help

...

Для более старого klogd нужная нам возможность (изменить порог вывода) - это ключ -c. Для модульного rsyslogd, идущего на смену sysogd и klogd - это определяется в его конфигурационном файле /etc/rsyslog.conf, где находим такие строки:

$ cat /etc/rsyslog.conf

....

#### RULES ####

# Log all kernel messages to the console.

# Logging much else clutters up the screen.

#kern.* /dev/console

...

Раскомментируем эту строку, немного изменив её вид:

kern.* /dev/tty12

- после этого вывод модулей будет направляться на консоль 12 (любую не инициированную, т.е. стандартно: с номером больше 6), на которую переключаемся: <Ctrl><Alt><F12>. Если мы хотим получать на экран сообщения не всех уровней, то эту строку перепишем по образцу:

kern.debug;kern.info;kern.notice;kern.warn /dev/tty12

После этого нужно заставить демон перечитать правленый конфигурационный файл, для чего можно: а). перезапустить демон (что более хлопотно), б). направить ему сигнал SIGHUP (по такому сигналу многие из демонов Linux перечитывают и обновляют свою конфигурацию):

$ ps -Af | grep logd

root 14614 1 0 21:34 ? 00:00:00 /sbin/rsyslogd -c 4

root 14778 12935 0 21:37 pts/14 00:00:00 grep logd

# kill -HUP 14614

При этом в системном журнале (или в текстовой консоли вывода) вы должны увидеть строки:

# cat /var/log/messages | tail -n2

Apr 3 21:37:34 notebook kernel: imklog 4.4.2, log source = /proc/kmsg started.

Apr 3 21:37:34 notebook rsyslogd: [origin software="rsyslogd" swVersion="4.4.2" x-pid="14614" x-info="http://www.rsyslog.com"] (re)start

Уровни диагностики в /proc

Ещё один механизм управления (динамического) уровнями диагностического вывода реализован через файловую систему /proc:

$ cat /proc/sys/kernel/printk

3 4 1 7

- где цифры последовательно показывают установленные уровни вывода; нас интересует первое значение - максимальный уровень сообщений, которые ещё будут выводиться на текстовую консоль.

Записав в этот файл новое значение, можно изменить значения, используемые по умолчанию. Но сделать это не так просто (из-за прав доступа к файлу):

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

bash: /proc/sys/kernel/printk: Отказано в доступе

$ sudo echo 8 > /proc/sys/kernel/printk

bash: /proc/sys/kernel/printk: Отказано в доступе

$ ls -l /proc/sys/kernel/printk

-rw-r--r-- 1 root root 0 Июн 13 16:09 /proc/sys/kernel/printk

Сделать это можно только с терминала с регистрацией под именем root :

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

$ cat /proc/sys/kernel/printk

8 4 1 7


Предыдущий раздел: Оглавление Следующий раздел:
Структура модуля   Основные ошибки модуля