Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are dev_*() family functions useful while debugging the Linux kernel?

While searching for techniques to debugging a Linux kernel, one of the ways is to use the dev_*() family functions.

These functions are defined in the /include/linux/device.h file.

The function list is as below:

`dev_emerge()`<br>
`dev_alert()`<br>
`dev_crit()`<br>
`dev_err()`<br>
`dev_warning()`<br>
`dev_notice()`<br>
`dev_info()`<br>

I have already experimented with the pr_*()[pr_emerge(), pr_alert(), pr_crit()...] family functions, which are similar to printk() in some way.

An experiment is done using simple kernel modules where I'm calling these functions. Furthermore I have also gone through a priority of messages displayed in syslog and dmesg (kernel ring buffer depending console_loglevel-a kernel variable).

But I'm unable to understand the use of dev_*() family. I mean, how do I use it in a program to debug kernel functionality?

like image 242
Novice Avatar asked Jul 13 '15 11:07

Novice


People also ask

How to debug Linux kernel using dev_* () function?

While searching for techniques to debugging a Linux kernel, one of the ways is to use the dev_* () family functions. These functions are defined in the /include/linux/device.h file. The function list is as below:

What is the use of debugfs?

After you mount debugfs, a large number of different directories and files will turn up in the /sys/kernel/debug/ directory. These are all virtual and dynamically generated by the kernel, like the files in procfs or sysfs. The files can be used to help debug different kernel subsystems, or just perused to see what is happening to ...

How stable is the debugfs filesystem?

The debugfs filesystem is also intended to not serve as a stable ABI to user space; in theory, there are no stability constraints placed on files exported there. The real world is not always so simple, though 1 ; even debugfs interfaces are best designed with the idea that they will need to be maintained forever. (Or an equivalent /etc/fstab line).

Why is err_PTR (-enodev) returned when using debugfs?

If ERR_PTR (-ENODEV) is returned, that is an indication that the kernel has been built without debugfs support and none of the functions described below will work. The most general way to create a file within a debugfs directory is with:


3 Answers

The pr_*() functions are the same as plain printk(), but with the KERN_xxx log level already included.

The dev_*() functions are the same as the corresponding pr_*() functions, but also print identifying information about the struct device.

If your message is related to some device (which is normally the case in drivers), you should use dev_*(). For example, in a USB driver:

struct usb_device *usb_dev;
dev_info(&usb_dev->dev, "hello\n");

struct usb_interface *usb_intf;
dev_info(&usb_intf->dev, "hello\n");

or in a PCI driver:

struct pci_dev *pci;
dev_info(&pci->dev, "hello\n");
like image 128
CL. Avatar answered Nov 01 '22 17:11

CL.


dev_* functions are similar to pr_*, but also print some information about device(struct device), passed to them as the first argument. This information may help to filter system log for messages, belonging to concrete device.

So, you can use dev_* function instead of pr_* whenever message is applicable to concrete device(and you have destriptor of it).

like image 40
Tsyvarev Avatar answered Nov 01 '22 17:11

Tsyvarev


Check what it prints yourself with QEMU

This is what it prints for a PCI device:

<6>lkmc_pci 0000:00:04.0: pci_probe

which is of format:

<level><kernel-module> <pci-address>: <message>

So as others said, it gives extra device information compared to a simple printk, namely:

  • kernel module name
  • PCI address

I tested that with QEMU's "edu" device, which is simple educational PCI device, for which I wrote a minimal Linux kernel module.

The key module code is:

static int pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{   
    dev_info(&(dev->dev), "pci_probe\n");

Character devices don't expose a struct device apparently, so you can't test it that way: How do you get a struct device for a Linux character device