LOG(7)
НАЗВАНИЕ
log - интерфейс для регистрации ошибок и трассировки
событий псевдоустройств
ОПИСАНИЕ
Драйвер log обеспечивает интерфейс для процессов регистрации ошибок и трассировки событий псевдоустройств
[см. strerr(1M), strace(1M)]. Log предоставляет два отдельных интерфейса: интерфейс вызова функций из ядра,
через который драйверы и модули псевдоустройств передают сообщения для регистрации, а также набор команд для
системного вызова ioctl(2) для взаимодействия на прикладном уровне с процессами регистрации и трассировки, а
также для процессов, которым требуется регистрировать
свои собственные сообщения.
Вызов функций из ядра
Сообщения передаются для регистрации путем вызова из
ядра функции strlog:
#include <sys/stropts.h>
#include <sys/strlog.h>
#include <sys/log.h>
strlog (mid, sid, level, flags, fmt, arg1, ...)
short mid, sid;
char level;
unsigned short flags;
char *fmt;
unsigned int arg1;
Аргумент mid - это идентификатор модуля для модуля или
драйвера, посылающего сообщение для регистрации. Аргумент sid задает дополнительный внутренний числовой
идентификатор, обычно используемый для идентификации
младшего устройства в драйвере. Аргумент level - это
уровень приоритета трассировки, дающий возможность избирательной трассировки (пропуска сообщений с низким
приоритетом). Аргумент flags представляет собой комбинацию следующих значений:
- SL_ERROR
- Сообщение зарегистрировать, как ошибку.
- SL_TRACE
- Трассировочное сообщение.
- SL_FATAL
- Фатальная ошибка.
- SL_NOTIFY
- Послать сообщение системному администратору через
mail(1).
Аргумент fmt - это цепочка символов, задающая формат в
стиле printf(3S), но спецификаторы %s, %e, %E, %g и %G
не обрабатываются. Количество дополнительных числовых
аргументов (arg1, ...) ограничено величиной NLOGARGS (в
настоящий момент оно равно 3).
Интерфейс пользователя
Доступ к интерфейсу log обеспечивается путем открытия
устройства /dev/log через драйвер clone(7). Каждое открытие устройства /dev/log образует отдельный поток к
драйверу log. Чтобы получать сообщения от драйвера log,
процесс должен оповестить драйвер с помощью команды
I_STR системного вызова ioctl(2) о своем желании обрабатывать сообщения об ошибках или трассировочные сообщения, указав в качестве третьего аргумента для системного вызова ioctl адрес структуры типа struct strioctl.
struct strioctl {
int ic_cmd; /* Команда */
int ic_timout; /* Таймаут */
int ic_len; /* Длина данных */
char *ic_dp; /* Указатель на данные */
};
Для того, чтобы обрабатывать сообщения об ошибках, необходимо в поле ic_cmd передаваемой структуры записать
константу I_ERRLOG, в поле ic_len - 0, а в поле ic_dp NULL. Для того, чтобы обрабатывать трассировочные сообщения, необходимо в поле ic_cmd передаваемой структуры
записать константу I_TRCLOG, в поле ic_dp задать адрес
массива структур типа struct trace_ids, а в поле ic_len
- длину этого массива в байтах.
struct trace_ids {
short ti_mid;
short ti_sid;
char ti_level;
};
Каждый элемент массива задает значения идентификатора
модуля, идентификатора устройства и уровня принимаемых
сообщений. Функция strlog будет выдавать только те сообщения, для которых значения идентификаторов модуля и
устройства совпадают с указанными в массиве, а значение
уровня не превосходит указанного в массиве. Задание
значения -1 в любом из полей ti_mid, ti_sid, ti_level
означает отсутствие соответствующих ограничений.
В каждый момент времени только один процесс может обрабатывать сообщения об ошибках и только один процесс может обрабатывать трассировочные сообщения.
После того, как процесс с помощью системного вызова
ioctl об явил, что он будет обрабатывать сообщения, log
начинает посылать ему все сообщения, удовлетворяющие
указанным ограничениям. Эти сообщения можно получить с
помощью системного вызова getmsg(2).
Управляющая область сообщения содержит структуру типа
struct log_ctl, в которой указаны идентификаторы модуля
и устройства, уровень, флаги, время посылки сообщения в
тактах часов от последней загрузки системы, то же время
в секундах от 1 января 1970 года и порядковый номер.
struct log_ctl {
short mid;
short sid;
char level;
short flags;
long ltime; /* Время в тактах от загрузки */
long ttime; /* Время в секундах от 1.01.1970 */
long seq_no; /* Порядковый номер */
};
Время в секундах от 1 января 1970 года позволяет узнать, когда было послано сообщение, а время в тактах
позволяет получить информацию об интервалах между сообщениями. Поддерживаются два ряда последовательных номеров: для сообщений об ошибках и для трассировочных сообщений. Пропуски в порядковых номерах позволяют определить факт потери сообщений при чересчур высокой интенсивности обменов.
Область данных сообщения содержит формат - цепочку символов, оканчивающуюся нулем, за которым следуют выровненные по границе слова NLOGARGS слов, представляющих
аргументы для этого формата.
Любой процесс, даже не являющийся обработчиком ошибок
или трассировок, может посылать сообщения подобной
структуры драйверу log. При этом в управляющей области
сообщения в структуре log_ctl можно задать только поля
level и flags, остальные поля перед передачей на обработку заполняет сам драйвер log. Область данных должна
содержать формат, за которым, выравненные по границе
слова, могут следовать до NLOGARGS слов, представляющих
аргументы.
Попытка задания команд I_ERRLOG или I_TRCLOG, когда уже
существует процесс-обработчик того же типа, приводит к
ошибке с кодом ENXIO. Та же ошибка ENXIO выдается, если
для команды I_TRCLOG не задан массив структур
trace_ids, а также если третий аргумент в команде I_STR
некорректен. Сообщения для драйвера log из программы
пользователя, которые имеют неправильную структуру, игнорируются без сообщений об ошибках.
ПРИМЕРЫ
- Пример запроса на обработку сообщений об ошибках:
struct strioctl ioc;
ic.ic_cmd = IERRLOG;
ic.ic_timeout = 0; /* Таймаут по умолчанию (15 с) */
ic.ic_len = 0;
ic.ic_dp = NULL;
ioctl (log, I_STR, &ioc);
- Пример запроса на обработку трассировочных сообщений:
struct strioctl ioc;
struct trace_ids tid [2];
tid[0].ti_mid = 2;
tid[0].ti_sid = 0;
tid[0].ti_level = 1;
tid[1].ti_mid = 1002;
tid[1].ti_sid = -1; /* Любой */
tid[1].ti_level = -1; /* Любой */
ic.ic_cmd = ITRCLOG;
ic.ic_timeout = 0;
ic.ic_len = 2 * sizeof (struct trace_ids);
ic.ic_dp = (char *) tid;
ioctl (log, I_STR, &ioc);
- Пример передачи сообщений драйверу log (без аргументов):
struct strbuf ctl, dat;
struct log_ctl lc;
char *message = "I am waiting for you";
ctl.len = ctl.maxlen = sizeof (lc);
ctl.buf = (char *) &lc;
dat.len = dat.maxlen = strlen (message) + 1;
dat.buf = message;
lc.level = 0;
lc.flags = SL_ERROR | SL_NOTIFY;
putmsg (log, &ctl, &dat, 0);
ФАЙЛЫ
/dev/log
<sys/stropts.h>
<sys/log.h>
<sys/strlog.h>
СМ. ТАКЖЕ
strace(1M), strerr(1M), clone(7).
intro(2), getmsg(2), ioctl(2), putmsg(2) в Справочнике
программиста.