您尚未登录。

楼主 # 2022-01-22 22:47:05

cwd502
会员
注册时间: 2021-12-25
已发帖子: 5
积分: 2

Linux内核驱动各种debug汇总

1.printk
(1)printk打印等级类型如下:
  printk(KERN_DEBUG "hello"); //
   #define KERN_EMERG    KERN_SOH "0"    /* system is unusable */
    #define KERN_ALERT    KERN_SOH "1"    /* action must be taken immediately */
    #define KERN_CRIT    KERN_SOH "2"    /* critical conditions */
    #define KERN_ERR    KERN_SOH "3"    /* error conditions */
    #define KERN_WARNING    KERN_SOH "4"    /* warning conditions */
    #define KERN_NOTICE    KERN_SOH "5"    /* normal but significant condition */
    #define KERN_INFO    KERN_SOH "6"    /* informational */
    #define KERN_DEBUG    KERN_SOH "7"    /* debug-level messages */
(2)printk开启打印
使用:
cat /proc/sys/kernel/printk
7    4    1    7   4(新版Linux才有)
echo 8 > /proc/sys/kernel/printk //8 > KERN_DEBUG, so KERN_DEBUG will print
分析:
kernel/printk/prink.c有如下定义:
int console_printk[5] = {
    CONSOLE_LOGLEVEL_DEFAULT,    /*7,console_loglevel,         控制台输出,<7 的才输出 */
    MESSAGE_LOGLEVEL_DEFAULT,    /*6,default_message_loglevel, 即printk(“hell world”);优先级为4  */
    CONSOLE_LOGLEVEL_MIN,        /*1,minimum_console_loglevel, 最小支持的打印等级为1,0留给内核严重错误使用 */
    CONSOLE_LOGLEVEL_DEFAULT,    /*7,default_console_loglevel, 第一个默认的等级*/
    MESSAGE_LOGLEVEL_DEFAULT,    /*4,default_devkmsg_loglevel, 进入kmesg /dev/kmsg log的等级*/
};
(1)第一个参数7:表示小于7优先级消息才会被输出到控制台。
(2)第二个参数4 :表示默认的printk消息优先级别,即printk(“hell world”);优先级为4, 由于4<7,故可以被打印到控制台。
(3)第三个参数1 :表示可接收的最高优先级,当printk disable控制台输出时,设置第一个参数为1,但是,从内核等级来看,还有优先级0,这个是printk最高级优先级,一般用于内核严重消息打印。比如内存错误或者 watchdog reset.也可以设置第一个和第三个参数为0
(4)第四个参数7: 默认控制台优先级,即第一个参数的默认优先级。
(5)第五个参数4:执行dmesg(/dev/kmsg)输出log,该等级即是消息进入log的等级,<4 的消息都能在dmesg下找到。

2. dev_dbg、 pr_debug、dev_vdbg、dev_printk
dev_dbg定义:
#if defined(CONFIG_DYNAMIC_DEBUG) //如果定义动态调试,执行echo 'file hub.c +p' > /sys/kernel/debug/dynamic_debug/control 开启打印
#define dev_dbg(dev, format, ...)             \
do {                             \
    dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG)  //定义了debug,则 dev_printk(KERN_DEBUG""), 执行 echo 8 > /proc/sys/kernel/printk 开启打印
#define dev_dbg(dev, format, arg...)        \
    dev_printk(KERN_DEBUG, dev, format, ##arg)
#else  //不打印
#define dev_dbg(dev, format, arg...)                \
({                                \
    if (0)                            \
        dev_printk(KERN_DEBUG, dev, format, ##arg);    \
})
#endif
pr_debug定义:
/* If you are writing a driver, please use dev_dbg instead */
#if defined(CONFIG_DYNAMIC_DEBUG)
#include <linux/dynamic_debug.h>

/* dynamic_pr_debug() uses pr_fmt() internally so we don't need it here */
#define pr_debug(fmt, ...) \
    dynamic_pr_debug(fmt, ##__VA_ARGS__) //动态调试
#elif defined(DEBUG)
#define pr_debug(fmt, ...) \
    printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) //正常打印
#else
#define pr_debug(fmt, ...) \
    no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__) //不打印
#endif
dev_vdbg定义:
#ifdef VERBOSE_DEBUG //定义了这个才打印
#define dev_vdbg    dev_dbg
#else
#define dev_vdbg(dev, format, arg...)                \
({                                \
    if (0)                            \
        dev_printk(KERN_DEBUG, dev, format, ##arg);    \
})
#endif

dev_printk定义:
static void __dev_printk(const char *level, const struct device *dev,
            struct va_format *vaf)
{
    if (dev) //带个前缀
        dev_printk_emit(level[1] - '0', dev, "%s %s: %pV", dev_driver_string(dev), dev_name(dev), vaf);
    else
        printk("%s(NULL device *): %pV", level, vaf);
}
void dev_printk(const char *level, const struct device *dev,
        const char *fmt, ...)
{
    struct va_format vaf;
    va_list args;
    va_start(args, fmt);
    vaf.fmt = fmt;
    vaf.va = &args;
    __dev_printk(level, dev, &vaf);
    va_end(args);
}
EXPORT_SYMBOL(dev_printk);

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn