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



posted @ 2021-06-18 11:07  王阳开  阅读(2172)  评论(0)    收藏  举报