Потеря данных и усечение printk
Я использую printk в своем загружаемом модуле ядра для регистрации параметров системных вызовов. Для каждого системного вызова несколько printks используются для печати переменных, для которых они появляются с "\t" в качестве разделителей. Чтобы перенаправить данные в буфере журнала ядра в другой файл, отличный от system /var/log/messages, я использую "klogd -f" для обхода интерфейса системного журнала. Полученные данные журнала составляют одну строку на системный вызов. Однако после анализа данных я обнаружил, что существует 2 проблемы.
Проблема 1: данные могут быть потеряны.
Проблема 2: данные одного системного вызова смешиваются с данными, принадлежащими другому системному вызову, возможно, посередине.
Вопрос 1: потеря данных вызвана переполнением буфера журнала ядра, которое перезаписывает самый старый журнал в буфере? Если так, как это преодолеть? Я планирую увеличить размер буфера журнала ядра. Как вы думаете, это уместно и какой размер лучше?
Вопрос 2: может ли системный вызов опередить другой системный вызов? Или в некоторых ситуациях один системный вызов может вызвать другой системный вызов и не может завершиться, если не вызванный завершается? Это причина того, что данные смешиваются друг с другом?
Вопрос 3: является ли printk атомарным? Если нет, то как сделать printk атомарным? Добавить блокировку, чтобы сделать ее непрерывной?
1 ответ
Если вы просто хотите получить дамп всех системных вызовов (с аргументами), которые выполняет программа, проверьте strace
команда.
Вопрос 1: вроде. Буфер журнала ядра реализован как кольцевой буфер. Если кольцевой буфер равен 128 КБ и ядро записывает в общей сложности 129 КБ данных с момента загрузки, первый 1 КБ перезаписывается новейшими данными. Вы можете увеличить размер этого буфера с помощью аргумента загрузки ядра log_buf_len
или во время компиляции в файле вашего ядра.config. Вы также можете изменить размер кольцевого буфера с помощью команды dmesg, запустив dmesg -s524288
который установит его на 512 КБ. Вы должны будете определить лучший размер в зависимости от количества данных, которые вы выплевываете.
Вопрос 2: Возможно, что один системный вызов прервет другой системный вызов, и в ядре существует множество других случаев прерывания - программы обработки прерываний являются ярким примером. Кроме того, если вы работаете в многоядерной системе, у вас может быть несколько активных потоков ядра.
Вопрос 3: Я считаю, что printk пытается получить блокировку кольцевого буфера ядра. Это немного сложно, так как вы можете вызвать printk из состояния паники.