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?
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");
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).
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
Related
I want to write a function in my custom kernel module, which can perform 'traverse through all devices attached to system and get their struct device*', in order to unregister all device drivers using driver_unregister(struct device_driver *drv) with device_driver* field of struct device as argument.
Expecting to find something like list_head head_of_all_devices as a global variable (so I can use things such as list_for_each_entry to access every device), I had took a look at struct device_node *of_node inside of struct device, ended up sadly as it is only used in ARM architecture not in x86.
To summarize, is there any data structure or kernel API function that allows kernel module programmer to traverse through all device's struct device* in a simple manner?
I am trying to implement a ULP in a Linux kernel module, and have been looking at the function pointers in the global variable struct proto tcp_prot, so that I can get a feel of which function pointer fields to copy into my own struct proto and which fields to override with my own implementation. One of the fields of struct proto is disconnect, which is set to the kernel function tcp_disconnect. However, I can't seem to find a user-space analogue of this function, and Google is not yielding anything useful. So what's the purpose of tcp_disconnect? What does it do and when is it invoked?
Like most protocol stacks the TCP/IP stack in the linux kernel is implemented as a state machine, this is i.e. in https://wiki.aalto.fi/download/attachments/70789052/linux-tcp-review.pdf on page 5. So the TCP protocol is not fully exported to user space, instead there is 'hidden communication' between the machines.
The source code for tcp_disconnect() in the TCP state machine in the linux kernel is in https://elixir.bootlin.com/linux/v4.6/source/net/ipv4/tcp.c#L2191
http://www.tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm
I want to write a linux kernel module which sends a character over tty to another PC.
Before anyone asks: Yes, it has to be a kernel module. User space isn't available at the point the "message" is send.
What I've got so far is:
I'm using kernel 4.14.
The device file is /dev/ttyS0
The major number for the driver is 4.
I've got a self written kernel module consisting of a function which is executed at the right time.
The problem at hand is, that I don't know how to access the tty driver using the name "ttyS0".
There are so many functions inside the tty driver and I haven't either the tty_struct nor the index (minor number) of the device...
The goal is probrably something like this pseudocode:
void MyFunction(void)
{
tty_struct MyStruct* = get_tty_struct("ttyS0");
char message = 'A';
write_to_tty(MyStruct, message);
}
Any help on the subject is appreciated.
Greetings
Example: I use sensor TMP421 which driver is linux/drivers/hwmon/tmp421.c. It will export to /sys/class/hwmon/hwon0/.... And user can use cat command to read the temperatures. But my is request: I want to read it at kernel space to control some thing when the temperature reach to MAX values (example).
So how I can attach to get the device context to use the function
tmp421_data *tmp421_update_device(struct device *dev)
to read the temperature ?
Or is there another way ?
I don't want to use the cat command at my code.
Thanks
Just do bus_find_device_by_name on an i2c_bus_type. It should give you the correct device pointer relatively easily. You will also have to change the tmp421_update_device function from "static" to "exported" (and move tmp421_data structure to an external header).
If you don't want to alter drivers not of your own, you can still try to emulate the approach sysfs takes when accessing device information. The sysfs dirent will be accessible to you at the dev->kobj.sd field and it's a fairly simple data structure.
Critically, you need to call put_device() on the received device handle after you've finished with it (otherwise you will end up with kernel lock-up down the line because of "unreleasable" objects). If you're using the kobj.sd accessor, then sysfs_get()/sysfs_put() on it will also be required.
As said in https://stackoverflow.com/a/4407051/196561 ("How to use sysfs inside kernel module?") by shodanex
it is a Bad Idea (tm)
with link http://www.linuxjournal.com/article/8110
Driving Me Nuts - Things You Never Should Do in the Kernel - From Issue #133 Linux Journal, 2005 By Greg Kroah-Hartman
The article says that it is possible to use sys_open and sys_read from modules to open and read files:
old_fs = get_fs();
set_fs(KERNEL_DS);
fd = sys_open(filename, O_RDONLY, 0);
if (fd >= 0) {
/* read the file here */
sys_close(fd);
}
set_fs(old_fs);
Don't know will it work with files in /sys or not.
And Greg warns us:
I Never Told You about This.
In conclusion, reading and writing a file from within the kernel is a bad, bad thing to do. Never do it. Ever.
Better way may be to learn inter module communications, possibly with modifying the hwmon/tmp421.c.
I want to add a char device to /devices in my Linux directory via C code. Since I'm creating fictitious drivers that should only exist when I insmod my_module.ko, I want my module to create a device for me. Below is the part of my code which should add the device, but I only initialize my cdev struct and tell the kernel about it.
int start_mod(void){
//Because we are dealing with a fictitious device, I want
//the driver to create my two devices with arbitrarly
//assigned major numbers.
alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME); // This assigns my device name
// as well as asign Major # my driver uses
cdev_init(&(my_dev->my_cdev), &fops);// This initializes my cdev struct that the kernel uses to keep track of my device
my_dev->my_cdev.owner = THIS_MODULE;
my_dev->my_cdev.ops = &fops;// fops is my file operations struct
int err = cdev_add(&(my_dev->my_cdev), dev_num, COUNT);// this in theory should give a pointer to the kernel
// to my cdev struct that I have setup to exist in my other structure.
// Now I need to officially add my device to /devices folder.
return 0;
}
I'm not to sure what I need to do to officially add the char device to the kernel.
What you do is you use some of the newer registration functions in the kernel like class_create and device_create. This will allow udev to create your device.
Are you saying you wrote a driver without looking at any other drivers?
Because there is no shortage of examples about how to register a character device.
Look in
drivers/char
Those aforementioned functions are GPL-only, by the way, which has implications if you want to redistribute the code.
The mknod() system call used to be used...but only a root-privileged process can create devices in /dev usually.