由于这是一个 Linux 问题,我会注意我使用的是 OpenSUSE 12.1
我正在运行一个内核模块,基本上它是一个 CAN 总线模拟器,printk()
只要“总线”上有活动,它就会打印消息。
我现在正在使用 跟踪消息sudo cat /proc/kmsg
,但是当我开始将其他“设备”放在“总线”上时,kmsg 流量会大大增加,并且很难找到我的消息。
无论如何将“printk”消息从一个特定进程传输到文件?
编辑 我现在看到,如果我在调试消息中添加特定标签,有可能,还有其他方法吗?
由于这是一个 Linux 问题,我会注意我使用的是 OpenSUSE 12.1
我正在运行一个内核模块,基本上它是一个 CAN 总线模拟器,printk()
只要“总线”上有活动,它就会打印消息。
我现在正在使用 跟踪消息sudo cat /proc/kmsg
,但是当我开始将其他“设备”放在“总线”上时,kmsg 流量会大大增加,并且很难找到我的消息。
无论如何将“printk”消息从一个特定进程传输到文件?
编辑 我现在看到,如果我在调试消息中添加特定标签,有可能,还有其他方法吗?
是的你可以。所有内核消息都可以包含 syslog-ng 守护进程。对于这个守护进程,您可以编写自定义规则并将模块中的所有消息放入特定文件。先看看/etc/syslog-ng/syslog-ng.conf
更新
默认情况下,所有内核 print 和 printk 函数都将消息放入内核环形缓冲区。用户空间程序可以通过 /proc/kmsg 文件访问这个环形缓冲区。
syslog-ng 将从 /proc/kmsg 读取数据,然后通过过滤器(过滤器只是特殊模式)grep 输出并将数据放在不同的输出中(在本示例中它将只是文本文件)。如果在输出缓冲区中我们会找到内核模块“hello”的输出,syslog-ng 会将消息放入 /var/log/hello,所有其他消息将放入 /var/log/messages
模块源
#include <linux/module.h>
#include <linux/kernel.h>
#define MODNAME "[hello]"
int init_module(void)
{
printk(KERN_WARNING MODNAME "Hello world 1.\n");
return 1;
}
void cleanup_module(void)
{
printk(KERN_ALERT "Goodbye world 1.\n");
}
在insmod之后
insmod hello-1.ko
在 /var/log/messages 你可以找到:
9 月 20 日 17:46:20 ns1 内核:[96643.968650] [hello]Hello world 1。
好的,让我们配置 syslog-ng 以捕获 grep 日志消息(通过使用模式 [hello])
$cat /etc/syslog-ng/syslog-ng.conf
@version: 3.2
# $Header: /var/cvsroot/gentoo-x86/app-admin/syslog-ng/files/syslog-ng.conf.gentoo.3.2,v 1.1 2011/01/18 17:44:14 mr_bones_ Exp $
#
# Syslog-ng default configuration file for Gentoo Linux
options {
chain_hostnames(no);
stats_freq(43200);
mark_freq(3600);
};
source src {
unix-stream("/dev/log" max-connections(256));
internal();
file("/proc/kmsg");
};
destination messages { file("/var/log/messages"); };
# output file for ower module
destination hello_messages { file("/var/log/hello"); };
# grep patterns for ower module
filter f_hello { match("hello" value("MESSAGE")); };
filter f_kernel { facility(kern); };
log { source(src); destination(messages); };
log { source(src); destination(console_all); };
# target for logging
log { source(src); filter(f_hello); filter(f_kernel); destination(hello_messages); };
还有另一种方法可以实现这一点:使用任何最新内核的内置“ftrace”支持。
a) 对于非常大的 printk 流量,printk 可能会导致系统瓶颈甚至崩溃——然后您应该切换到使用 trace_printk();它的开销几乎是微不足道的(尤其是与 printk 相比) b) ftrace 能够为特定进程过滤 ftrace 环形缓冲区。
请在此处阅读详细信息(在任何最近的内核源代码树中): Documentation/trace/ftrace.txt
添加资源:“使用 Ftrace 调试内核 - 第 1 部分” http://lwn.net/Articles/365835/ (也请参见第 2 部分)。