linux内核提供函数dump_stack()来跟踪函数的调用过程,原理是通过打印当前cpu的堆栈的调用函数来显示当前的上下文环境与调用关系;
例:
创建一个混杂设备,并定义read函数。在read中加入dump_stack(),显示read调用关系。结果如下:
[ 1560.465491] CPU: 0 PID: 2759 Comm: cat Tainted: GF O 3.13.0-32-generic #57-Ubuntu
[ 1560.465494] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 07/02/2015
[ 1560.465496] 00000000 00000000 ddf47f58 c1650cd3 dc05e3c0 ddf47f64 e0937010 00000000
[ 1560.465502] ddf47f88 c1179238 ddf47f98 ddf47fac c1125645 00a000c9 dc05e3c0 00000000
[ 1560.465506] 09431000 ddf47fac c11799a9 ddf47f98 00010000 00000000 00000000 00000003
[ 1560.465511] Call Trace:
[ 1560.465521] [<c1650cd3>] dump_stack+0x41/0x52
[ 1560.465525] [<e0937010>] my_read+0x10/0x20 [test]
[ 1560.465529] [<c1179238>] vfs_read+0x78/0x140
[ 1560.465534] [<c1125645>] ? SyS_fadvise64_64+0x1e5/0x260
[ 1560.465537] [<c11799a9>] SyS_read+0x49/0x90
[ 1560.465542] [<c165efcd>] sysenter_do_call+0x12/0x28
#include <linux/init.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
int my_read(struct file *file, char __user *user, size_t size, loff_t * loff)
{
dump_stack();
printk(KERN_INFO "This is miscdevice read\n");
return 0;
}
int my_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "This is miscdevice open\n");
return 0;
}
int my_close(struct inode *inode, struct file *file)
{
printk(KERN_INFO "This is miscdevice close\n");
return 0;
}
const struct file_operations my_fops = {
.open = my_open,
.release = my_close,
.read = my_read,
};
struct miscdevice my_misc = {
.minor = 201,
.name = "stone",
.fops = &my_fops,
};
static __init int hello_init(void)
{
misc_register(&my_misc);
printk(KERN_ALERT "helloworld!\n");
return 0;
}
static __exit void hello_exit(void)
{
misc_deregister(&my_misc);
printk(KERN_ALERT "helloworld exit!\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stone");