As is well known to many, debugging messages in Linux regarding drivers are carried out by several subsets of macros and functions. Not all analogues are interchangeable and work as it seems logical at first glance. That is what this brief article will be about.
First, let's look at what known message output functions are provided in the core internal API.
Basic function
printk(LEVEL "message\n");
From it there is a set of macros (the most frequently used):
pr_err("message\n"); pr_warn("message\n"); pr_info("message\n"); pr_debug("message\n");
And so on.
')
For drivers, a set of functions with the prefix
dev_*
with the corresponding output levels is used, and separately for drivers of network cards with the prefix
netdev_*
. And in general, the general rule is that the kernel subsystem or driver uses its prefix with a message output level suffix.
All of them are full-fledged analogs of the
pr_*
record
printk(LEVEL …)
for
pr_*
and in the same way for
dev_*
and
netdev_*
except for
pr_debug()
,
dev_dbg()
and, as everyone has already guessed,
netdev_dbg()
.
So, under what conditions we will see the message displayed by different options?
With
printk(KERN_DEBUG "message\n")
:
- the output level on the kernel command line is set to either more than 7 or the ignore_loglevel parameter is passed
and
pr_debug("message\n")
:
- the output level on the kernel command line is set to either more than 7 or the ignore_loglevel parameter is passed
- the module of interest is built with the
DEBUG
option or the CONFIG_DYNAMIC_DEBUG
kernel configuration option is CONFIG_DYNAMIC_DEBUG
, and the corresponding messages (for example, indicating the module name: line number) are included in the list of output
Same for
dev_dbg()
, and for
netdev_dbg()
.
In addition, special attention should be paid to the useful option
CONFIG_DYNAMIC_DEBUG
. With all its dynamism, it does not begin to load the kernel itself, so not all modules can rely on it.
Another dilemma about what to use in the product version:
CONFIG_DYNAMIC_DEBUG
or standard output, prefixed by a type condition:
#define mydbg(dev, format, arg…) \ do { \ if (mycooldriver->debug > 0) \ dev_printk(KERN_DEBUG, dev, format, ##arg); \ } while (0)
So the difference here is quite obvious, if you dig into the depths of the kernel source code, namely, in the first case, the output will be equal to no-op (empty operation), which is not so in the second case. Accordingly, modules that are critical in terms of execution time should not be filled with the code shown above. Moreover, the best option would be to use trace points in such places, but I will tell you about this sometime in the future.
Bonus add that function
print_hex_dump_bytes()
relatively recently acquired support from the Dynamic Debug.