Библиотека сайта rus-linux.net
Цилюрик О.И. Модули ядра 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
Предыдущий раздел: | Оглавление | Следующий раздел: |
Структура модуля | Основные ошибки модуля |