http://www.csdn.net/ http://www.arm.com/zh/ https://www.kernel.org/ http://www.linuxpk.com/ http://www.51develop.net/ http://linux.chinaitlab.com/ http://www.embeddedlinux.org.cn http://bbs.pediy.com/
分类: linux
2018-08-27 14:30:53
一直都知道内核printk分级机制,但是没有去了解过,前段时间和一个同事聊到开机启动打印太多,只需要设置一下等级即可;另外今天看驱动源码,也看到类似于printk(kern_err "....")的打印信息,以前用都是直接printk("...."),今晚回来就把printk这个机制熟悉一下。
转自:
另外/var/log下20个linux日志文件详解
#define kern_emerg "<0>" /* 系统不可使用 */ #define kern_alert "<1>" /* 需要立即采取行动 */ #define kern_crit "<2>" /* 严重情况 */ #define kern_err "<3>" /* 错误情况 */ #define kern_warning "<4>" /* 警告情况 */ #define kern_notice "<5>" /* 正常情况, 但是值得注意 */ #define kern_info "<6>" /* 信息型消息 */ #define kern_debug "<7>" /* 调试级别的信息 */ /* 使用默认内核日志级别 */ #define kern_default "" /* * 标注为一个“连续”的日志打印输出行(只能用于一个 * 没有用 \n封闭的行之后). 只能用于启动初期的 core/arch 代码 * (否则续行是非smp的安全). */ #define kern_cont " "
/* printk's without a loglevel use this.. */ #define default_message_loglevel config_default_message_loglevel
printk(kern_emerg "log_level:%s\n", kern_emerg);
printk( "<0>" "log_level:%s\n", kern_emerg);
kern_levels.h printk.h printk.c 几个文件里面分别定义了printk和console的printk显示等级
echo 8 > /proc/sys/kernel/printk设置console的loglevel
#include#include #include <string.h> #include //#define __library__ /* _syscall3 and friends are only available through this */ //#include /* define the system call, to override the library function */ //_syscall3(int, syslog, int, type, char *, bufp, int, len); int main(int argc, char **argv) { int level; if (argc == 2) { level = atoi(argv[1]); /* the chosen console */ } else { fprintf(stderr, "%s: need a single arg\n", argv[0]); exit(1); } if (klogctl(8, null, level) < 0) { fprintf(stderr, "%s: syslog(setlevel): %s\n", argv[0], strerror(errno)); exit(1); } exit(0); }
#ifndef pr_fmt #define pr_fmt(fmt) fmt #endif #define pr_emerg(fmt, ...) \ printk(kern_emerg pr_fmt(fmt), ##__va_args__) #define pr_alert(fmt, ...) \ printk(kern_alert pr_fmt(fmt), ##__va_args__) #define pr_crit(fmt, ...) \ printk(kern_crit pr_fmt(fmt), ##__va_args__) #define pr_err(fmt, ...) \ printk(kern_err pr_fmt(fmt), ##__va_args__) #define pr_warning(fmt, ...) \ printk(kern_warning pr_fmt(fmt), ##__va_args__) #define pr_warn pr_warning #define pr_notice(fmt, ...) \ printk(kern_notice pr_fmt(fmt), ##__va_args__) #define pr_info(fmt, ...) \ printk(kern_info pr_fmt(fmt), ##__va_args__) #define pr_cont(fmt, ...) \ printk(kern_cont fmt, ##__va_args__) /* 除非定义了debug ,否则pr_devel()不产生任何代码 */ #ifdef debug #define pr_devel(fmt, ...) \ printk(kern_debug pr_fmt(fmt), ##__va_args__) #else #define pr_devel(fmt, ...) \ no_printk(kern_debug pr_fmt(fmt), ##__va_args__) #endif /* 如果你在写一个驱动,请使用dev_dbg */ #if defined(debug) #define pr_debug(fmt, ...) \ printk(kern_debug pr_fmt(fmt), ##__va_args__) #elif defined(config_dynamic_debug) /* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */ #define pr_debug(fmt, ...) \ dynamic_pr_debug(fmt, ##__va_args__) #else #define pr_debug(fmt, ...) \ no_printk(kern_debug pr_fmt(fmt), ##__va_args__) #endif
在调试的时候,有时某些部分可能printk会产生大量输出, 导致系统无法正常工作,并可能使系统日志ring buffer溢出(旧的信息被快速覆盖)。特别地,当使用一个慢速控制台设备(如串口), 过量输出也能拖慢系统。这样反而难于发现系统出问题的地方。所以你应当非常注意:正常操作时不应当打印任何东西,打印的输出应当是指示需要注意的异常,并小心不要做过头。
#define printk_ratelimit() __printk_ratelimit(__func__)
这个函数应当在你认为打印一个可能会出现大量重复的消息之前调用,如果这个函数返回非零值, 继续打印你的消息, 否则跳过它。典型的调用如这样:
if (printk_ratelimit()) printk(kern_notice "the printer is still on fire\n");
static char __log_buf[__log_buf_len];
/* * 在指向log_buf时并没有用log_buf_len做限制 - 所以他们 * 在作为下标使用前必须用掩码处理(去除config_log_buf_shift以上的高位) */ static unsigned log_start; /* log_buf中的索引: 指向由syslog()读取的下一个字符 */ static unsigned con_start; /* log_buf中的索引: 指向发送到console的下一个字符 */ static unsigned log_end; /* log_buf中的索引:最近写入的字符地址 1 */