[kernel]内核日志及printk结构分析
一直都知道内核printk分级机制,但是没有去了解过,前段时间和一个同事聊到开机启动打印太多,只需要设置一下等级即可;另外今天看驱动源码,也看到类似于Printk(KERN_ERR "....")的打印信息,以前用都是直接printk("...."),今晚回来就把printk这个机制熟悉一下。
转自:http://blog.csdn.net/tangkegagalikaiwu/article/details/8572365
另外/var/log下20个Linux日志文件详解
http://h2appy.blog.51cto.com/609721/781281/
一、printk概述
- 函数名
- 能够更早地工作(输出信息)
- 她有自己的小缓存(一般为512B)
- 一次性输出到硬件设备,不再以ring buffer的形式保留信息。
二、printk的使用
(1)日志等级
#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 "<d>"
/*
* 标注为一个“连续”的日志打印输出行(只能用于一个
* 没有用 \n封闭的行之后). 只能用于启动初期的 core/arch 代码
* (否则续行是非SMP的安全).
*/
#define KERN_CONT "<c>"
/* 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
- 一种选择是保持终端的默认记录等级不变,给所有调试信息KERN CRIT或更低的等级以保证信息一定会被输出。
- 另一种方法则相反,给所有调试信息KERN DEBUG等级,而调整终端的默认记录等级为7,也可以输出所有调试信息。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
//#define __LIBRARY__ /* _syscall3 and friends are only available through this */
//#include <linux/unistd.h>
/* 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 == ) {
level = atoi(argv[]); /* the chosen console */
} else {
fprintf(stderr, "%s: need a single arg\n", argv[]);
exit();
}
if (klogctl(, NULL, level) < ) {
fprintf(stderr, "%s: syslog(setlevel): %s\n",
argv[], strerror(errno));
exit();
}
exit();
}
(2)相关辅助宏
#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
(3)输出速率控制
在调试的时候,有时某些部分可能printk会产生大量输出, 导致系统无法正常工作,并可能使系统日志ring buffer溢出(旧的信息被快速覆盖)。特别地,当使用一个慢速控制台设备(如串口), 过量输出也能拖慢系统。这样反而难于发现系统出问题的地方。所以你应当非常注意:正常操作时不应当打印任何东西,打印的输出应当是指示需要注意的异常,并小心不要做过头。
#define printk_ratelimit() __printk_ratelimit(__func__)
这个函数应当在你认为打印一个可能会出现大量重复的消息之前调用,如果这个函数返回非零值, 继续打印你的消息, 否则跳过它。典型的调用如这样:
if (printk_ratelimit())
printk(KERN_NOTICE "The printer is still on fire\n");
- /proc/sys/kern/printk_ratelimit( 可以看作一个监测周期,在这个周期内只能发出下面的控制量的信息)
- /proc/sys/kernel/printk_ratelimit_burst(以上周期内的最大消息数,如果超过了printk_ratelimit()返回0)
(4)最后特别提醒
三、printk的内核实现
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 */
四、用户空间访问内核日志
- 通过glibc的klogctl函数接口调用内核的syslog系统调用
- 通过fs/proc/kmsg.c内核模块中导出的procfs接口:/proc/kmsg文件。

[kernel]内核日志及printk结构分析的更多相关文章
- [linux-内核][转]内核日志及printk结构浅析
这段时间复习了一下内核调试系统,注意看了一下printk的实现以及内核日志的相关知识,这里做一下总结. 1.问题的引出: 做DPDK项目时,调试rte_kni.ko时,发现printk并不会向我们想想 ...
- 内核日志及printk结构浅析
作者:tekkamanninja 鸣谢:感谢ChinaUnix技术社区的tekkamanninja提供稿件 ,如需转载,请注明出处. 这段时间复习了一下内核调试系统,注意看了一下printk的实现 ...
- ECS实例中的应用偶尔出现丢包现象并且内核日志(dmesg)存在“kernel: nf_conntrack: table full, dropping packet”的报错信息
问题描述 连接ECS实例中的应用时偶尔出现丢包现象.经排查,ECS实例的外围网络正常,但内核日志(dmesg)中存在"kernel: nf_conntrack: table full, dr ...
- Linux内核日志开关
Linux内核日志开关 1.让pr_debug能输出 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -59,7 +59,7 ...
- 深入linux kernel内核配置选项
============================================================================== 深入linux kernel内核配置选项 ...
- tiny4412 串口驱动分析八 --- log打印的几个阶段之内核启动阶段(printk tiny4412串口驱动的注册)
作者:彭东林 邮箱:pengdonglin137@163.com 开发板:tiny4412ADK+S700 4GB Flash 主机:Wind7 64位 虚拟机:Vmware+Ubuntu12_04 ...
- Ubuntu系统---系统驱动丢失、Kernel内核卸载、禁止更新
Ubuntu系统---系统驱动丢失.Kernel内核卸载.禁止更新 一早开机发现,ubuntu字体异常,字体很大,直接反应是驱动坏了.一查,确实丢失英伟达驱动,为什么呢?莫名的消失.想知道:1.英伟达 ...
- linux内核源码目录结构分析
原文地址 /arch.arch是architecture的缩写.arch目录下是好多个不同架构的CPU的子目录,譬如arm这种cpu的所有文件都在arch/arm目录下,X86的CPU的所有文件都在a ...
- Linux 内核日志——dmesg
有时Linux系统或者系统上运行的mysqld或者其它进程,会发生一些莫名其妙的问题,比如突然挂掉了,比如突然重启等等.在软件上找不到问题所在,此时我们应该怀疑硬件或者内核的问题,此时我们就可以使用 ...
随机推荐
- GetXamarin.xambe
GetXamarin.xambe <!DOCTYPE html> <html lang="en" class=""> <head& ...
- Error: Cannot find module 'express' 之 解决方案
出现如题错误,是因为执行了#npm install -g express的缘故,express没有被写到package.json里面去. 解决也好办,在程序目录下执行#npm install expr ...
- 截短字符串的函数(JS中适用)
function cutShort(str){ if(str.length>15){ str=str.substr(0,15)+"..."; } ...
- Dubbo之旅--集群容错和负载均衡
当我们的系统中用到Dubbo的集群环境,由于各种原因在集群调用失败时,Dubbo提供了多种容错方案,缺省为failover重试. Dubbo的集群容错在这里想说说他是由于我们实际的项目中出现了此类的问 ...
- 委托批量处理Excel
在以前的博文中--CAD批量处理工具--BatchProc,即只要用户输入处理单个文件的代码,即可批量处理多个文件.使用起来特别方便. 在现在的地籍处理中,处理Excel的情况比较多,尤其需要反反复复 ...
- HDU 5312(数学推导+技巧)
首先说一下.N*(N-1)/2为三角形数,随意一个自然数都最多可由三个三角形数表示. 对于,对于给定的要求值 V, 那么其一组解可表示为 V = 6*(K个三角形数的和)+K: 即随意由k个数组成的解 ...
- Project Euler:Problem 76 Counting summations
It is possible to write five as a sum in exactly six different ways: 4 + 1 3 + 2 3 + 1 + 1 2 + 2 + 1 ...
- git:could not open a connection to your authentication agent
git:could not open a connection to your authentication agent 错误: vagrant@homestead:~/Code/sample$ ...
- MyEclipse中出现Address already in use:JVM_Bind:8080
今天在搭建环境,跑以前的一个项目时,出现了Address already in use 的错误,这显然是tomcat的端口号被占用了,我的机子上安装了appache和appache Tomcat: 我 ...
- 关于SQLite在Android开发中的知识点总结
一.存放位置 1.内部存储-放在 data/data 底下, 也就是内部存储, 里面的文件以及文件夹是私有的, 其他 app 不能访问, 也随着 app 卸载而删除; 2.放在 sd 卡里面, 如果设 ...