linux kernel debug printk
linux kernel debug printk
#if 1
#undef pr_dbg(fmt, args...)
#define pr_dbg(fmt, args...) \
printk(KERN_INFO "~~~ [module] %s() %d->"fmt, __FUNCTION__, __LINE__, ##args)
#else
#define pr_dbg(fmt, args...)
#endif
#undef dev_dbg(dev, format, arg...)
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG, dev, format, ##arg)
printk("%s()\n", __func__);
printk("%s() %d->\n", __FILE__, __FUNCTION__, __LINE__);
printk("~~~ %s() %d->\n", __FILE__, __FUNCTION__, __LINE__);
printk("%s() %d->\n", __FUNCTION__, __LINE__);
printk("~~~ %s() %d->\n", __FUNCTION__, __LINE__);
printk("~~~ %s() pid:%d, comm:%s\n", __func__, current->pid, current->comm);
printk(KERN_ERR "~~~ %s() pid:%d, comm:%s\n", __func__, current->pid, current->comm);
APP debug
printf("%s() %d->\n", __FUNCTION__, __LINE__);
printf("~~~ %s() %d->\n", __FUNCTION__, __LINE__);
config kernel debug log printk level
echo 8 > /proc/sys/kernel/printk
dev_info() dev_dbg()
include\linux\device.h
#ifdef CONFIG_PRINTK
...
extern __printf(2, 3)
void _dev_info(const struct device *dev, const char *fmt, ...);
#else
...
static inline __printf(2, 3)
void _dev_info(const struct device *dev, const char *fmt, ...)
{}
#endif
/*
* Stupid hackaround for existing uses of non-printk uses dev_info
*
* Note that the definition of dev_info below is actually _dev_info
* and a macro is used to avoid redefining dev_info
*/
#define dev_info(dev, fmt, arg...) _dev_info(dev, fmt, ##arg)
#if defined(CONFIG_DYNAMIC_DEBUG)
#define dev_dbg(dev, format, ...) \
do { \
dynamic_dev_dbg(dev, format, ##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG)
#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
drivers\base\core.c
...
/*
* Device logging functions
*/
#ifdef CONFIG_PRINTK
static int
create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen)
{
const char *subsys;
size_t pos = 0;
if (dev->class)
subsys = dev->class->name;
else if (dev->bus)
subsys = dev->bus->name;
else
return 0;
pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys);
if (pos >= hdrlen)
goto overflow;
/*
* Add device identifier DEVICE=:
* b12:8 block dev_t
* c127:3 char dev_t
* n8 netdev ifindex
* +sound:card0 subsystem:devname
*/
if (MAJOR(dev->devt)) {
char c;
if (strcmp(subsys, "block") == 0)
c = 'b';
else
c = 'c';
pos++;
pos += snprintf(hdr + pos, hdrlen - pos,
"DEVICE=%c%u:%u",
c, MAJOR(dev->devt), MINOR(dev->devt));
} else if (strcmp(subsys, "net") == 0) {
struct net_device *net = to_net_dev(dev);
pos++;
pos += snprintf(hdr + pos, hdrlen - pos,
"DEVICE=n%u", net->ifindex);
} else {
pos++;
pos += snprintf(hdr + pos, hdrlen - pos,
"DEVICE=+%s:%s", subsys, dev_name(dev));
}
if (pos >= hdrlen)
goto overflow;
return pos;
overflow:
dev_WARN(dev, "device/subsystem name too long");
return 0;
}
int dev_vprintk_emit(int level, const struct device *dev,
const char *fmt, va_list args)
{
char hdr[128];
size_t hdrlen;
hdrlen = create_syslog_header(dev, hdr, sizeof(hdr));
return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args);
}
EXPORT_SYMBOL(dev_vprintk_emit);
int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = dev_vprintk_emit(level, dev, fmt, args);
va_end(args);
return r;
}
EXPORT_SYMBOL(dev_printk_emit);
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);
#define define_dev_printk_level(func, kern_level) \
void func(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(kern_level, dev, &vaf); \
\
va_end(args); \
} \
EXPORT_SYMBOL(func);
define_dev_printk_level(dev_emerg, KERN_EMERG);
define_dev_printk_level(dev_alert, KERN_ALERT);
define_dev_printk_level(dev_crit, KERN_CRIT);
define_dev_printk_level(dev_err, KERN_ERR);
define_dev_printk_level(dev_warn, KERN_WARNING);
define_dev_printk_level(dev_notice, KERN_NOTICE);
define_dev_printk_level(_dev_info, KERN_INFO);
#endif
...
include\linux\dynamic_debug.h
...
#define dynamic_dev_dbg(dev, fmt, ...) \
do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
if (DYNAMIC_DEBUG_BRANCH(descriptor)) \
__dynamic_dev_dbg(&descriptor, dev, fmt, \
##__VA_ARGS__); \
} while (0)
...
dev_info(), 配置了CONFIG_PRINTK,dev_info相当于printk, 等级KERN_INFO, 调试新信息前加上打印 dev name;
dev_dbg(), 配置了CONFIG_DYNAMIC_DEBUG, 动态调试打印;动态调试打印; 使用debug fs, /sys/kernel/debug/dynamic_debug/control 动态配置打印;
没有配置CONFIG_DYNAMIC_DEBUG,如果定义了defined(DEBUG),相当于dev_printk(KERN_DEBUG, dev, format, ##arg);
没有配置CONFIG_DYNAMIC_DEBUG,也没定义DEBUG,不打印;
对某个内核驱动程序,需要直接让dev_dbg() 打印输出,可用宏定义,重新定义
#undef dev_dbg(dev, format, arg...)
#define dev_dbg(dev, format, arg...) \
dev_printk(KERN_DEBUG, dev, format, ##arg)
或者,文件开头
#undef CONFIG_DYNAMIC_DEBUG
#define DEBUG
...
pr_info() pr_debug()
include/linux/printk.h
...
/*
* These can be used to print at the various log levels.
* All of these will print unconditionally, although note that pr_debug()
* and other debug macros are compiled out unless either DEBUG is defined
* or CONFIG_DYNAMIC_DEBUG is set.
*/
#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__)
...
/* 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
...
pr_info(), #define pr_info(fmt, ...) printk(KERN_INFO pr_fmt(fmt), ##VA_ARGS)
pr_debug(), 如果配置了CONFIG_DYNAMIC_DEBUG,相当于dynamic_pr_debug();
如果没有配置CONFIG_DYNAMIC_DEBUG,且定义了DEBUG,相当于printk();
否则,相当于空函数,不打印;
pr_xx 打印函数名
#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
#include <linux/module.h>
reference:
https://cloud.tencent.com/developer/article/1819284
https://blog.csdn.net/W1107101310/article/details/80526039
https://blog.csdn.net/tonywgx/article/details/17504001