LOG(7) LOG(7) НАЗВАНИЕ log - интерфейс для регистрации ошибок и трассировки событий в ПОТОКАХ ОПИСАНИЕ Драйвер log обеспечивает интерфейс для процессов ре- гистрации ошибок и трассировки событий в ПОТОКАХ [см. strerr(1M), strace(1M)]. Log предоставляет два отдель- ных интерфейса: интерфейс вызова функций из ядра, через который ПОТОКОВЫЕ драйверы и модули передают сообщения для регистрации, а также набор команд для системного вызова ioctl(2) для взаимодействия на прикладном уровне с процессами регистрации и трассировки, а также для процессов, которым требуется регистрировать свои собст- венные сообщения. Вызов функций из ядра Сообщения передаются для регистрации путем вызова из ядра функции strlog: |#include |#include |#include | |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 из программы пользователя, которые имеют неправильную структуру, иг норируются без сообщений об ошибках. ПРИМЕРЫ 1. Пример запроса на обработку сообщений об ошибках: |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); 2. Пример запроса на обработку трассировочных сообще- ний: |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); 3. Пример передачи сообщений драйверу 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 СМ. ТАКЖЕ strace(1M), strerr(1M), clone(7). intro(2), getmsg(2), ioctl(2), putmsg(2) в Справочнике программиста.