• kernel printk信息显示级别


    涉及文件:kernel/printk.c include/linux/kernel.h
    用printk内核会根据日志级别把消息打印到当前控制台上。
    信息正常输出前提是--日志输出级别(msg_log_level)小于控制台级别(console_loglevle),
    内核中数字越小优先级越高。
    没有指定日志级别的printk默认级别是DEFAULT_MESSAGE_LOGLEVEL,
    默认级别一般为4,与KERN_WARNING一级别。
    在kernel/printk.c中定义:
    /* printk's without a loglevel use this.. */
    #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */

    #define DEFAULT_MESSAGE_LOGLEVEL CONFIG_DEFAULT_MESSAGE_LOGLEVEL /*3.2内核中可通过配置内核make menuconfig配置默认消息(日志级别), kernel hacking-> CONFIG_DEFAULT_MESSAGE_LOGLEVEL*/

    /* We show everything that is MORE important than this.. */
    #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
    #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
    69 int console_printk[4] = {
    70 DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
    71 DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
    72 MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */
    73 DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
    74 };
    日志级别一共有8级,定义于include/linux/kernel.c中
    102 #define KERN_EMERG "<0>" /* system is unusable */
    103 #define KERN_ALERT "<1>" /* action must be taken immediately */
    104 #define KERN_CRIT "<2>" /* critical conditions */
    105 #define KERN_ERR "<3>" /* error conditions */
    106 #define KERN_WARNING "<4>" /* warning conditions */
    107 #define KERN_NOTICE "<5>" /* normal but significant condition */
    108 #define KERN_INFO "<6>" /* informational */
    109 #define KERN_DEBUG "<7>" /* debug-level messages */

    111 /* Use the default kernel loglevel */
    112 #define KERN_DEFAULT "<d>"
    118 #define KERN_CONT "<c>"
    119
    120 extern int console_printk[];
    121
    122 #define console_loglevel (console_printk[0])
    123 #define default_message_loglevel (console_printk[1])
    124 #define minimum_console_loglevel (console_printk[2])
    125 #define default_console_loglevel (console_printk[3])
    ------------------------------------------------------------------------------------------
    其实printk始终是输出信息的,用户区/var/log/messages,
    内核态/proc/kmsg(klogd没运行,消息不会到用户区)。
    读写/proc/sys/kernel/printk可读取或修改控制台日志级别。
    #cat /proc/sys/kernel/printk
    6  4  1  7
    ==>控制台日志级别,默认消息日志级别,最低的控制台日志级别,默认的控制台日志级别。
    # echo '7 7 1 7' > /proc/sys/kernel/printk
    #echo '7 7' > /proc/sys/kernel/printk
    注:第二项是“默认消息日志级别”,当printk()中不设置日志级别时才采用默认消息日志级别。
    ----------------------------------------------------------------------------
    为了解决一个问题临时加调试信息可以有两种做法:
    一种选择是保持终端的默认记录等级不变,给所有调试信息KERN CRIT或更低的等级以保证信息一定会被输出。另一种方法则相反,给所有调试信息KERN DEBUG等级,而调整终端的默认记录等级为7,也可以输出所有调试信息。两种方法各有利弊。
    示例1:
    static int __init mm_init(void)
    {
    printk(KERN_INFO "Hi module! ");
    return 0;
    }
    static void __exit mm_exit(void)
    {
    printk(KERN_WARNING "Bye module! ");
    }
    模块测试:
    /mnt # insmod main.ko
    [ 2332.295166] Hi module!
    /mnt # cat /proc/sys/kernel/printk
    8 7 1 8
    /mnt # rmmod main
    [ 2585.805572] Bye module!
    /mnt # echo 4 > /proc/sys/kernel/printk
    /mnt # cat /proc/sys/kernel/printk
    4 7 1 8
    /mnt # insmod main.ko
    /mnt # rmmod main
    /mnt # echo 5 > /proc/sys/kernel/printk
    /mnt # insmod main.ko
    /mnt # rmmod main
    [ 3444.786712] Bye module!
    示例2:
    static int __init mm_init(void)
    {
    printk(KERN_ERR "Hi module! ");
    return 0;
    }
    static void __exit mm_exit(void)
    {
    printk("Bye module! ");
    }
    模块测试:
    /mnt # insmod main.ko
    [ 3606.503204] Hi module!
    /mnt # rmmod main.ko
    /mnt # cat /proc/sys/kernel/printk
    5 7 1 8
    /mnt # echo 5 4 > /proc/sys/kernel/printk
    /mnt # insmod main.ko
    [ 3679.207916] Hi module!
    /mnt # rmmod main
    [ 3684.487152] Bye module!
    /mnt # echo 3 4 > /proc/sys/kernel/printk
    /mnt # insmod main.ko
    /mnt # rmmod main
    -----------------------------------------------------------------------------
    采用日志级别的printk()在include/linux/printk.h中有其简便应用方法:
    #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应用,此应用必须在此文件中定义DEBUG,否则不能打印信息,其与日志级别和控制台日志级别无关(当然,其调用printk()的KERN_DEBUG级别,若要打印信息,还要满足此日志级别)。
    int no_printk(const char *fmt, ...)
    {
    return 0;
    }

    /* pr_devel() should produce zero code unless DEBUG is defined */
    #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

    /* If you are writing a driver, please use dev_dbg instead */
    #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

    参考:debug宏起作用应用

    参考:http://blog.chinaunix.net/uid-20543672-id-3211832.html

  • 相关阅读:
    查找父/子控件(元素、节点)
    【转载】单点系统架构的可用性与性能优化
    【转载】互联网架构,如何进行容量设计?
    【转载】细聊分布式ID生成方法
    【转载】秒杀系统架构优化思路
    【转载】程序员这口饭-职业规划解决方案
    【转载】一位软件工程师的6年总结
    【转载】VS工具使用——代码生成函数关系图
    【转载】VS工具使用——代码图
    【转载】一些VS2013的使用技巧
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/4824820.html
Copyright © 2020-2023  润新知