在Linux內核中提供了一個可以打印出內核調用堆棧的函數 dump_stack()
該函數在我們調試內核的過程中可以打印出函數調用關係,該函數可以幫助我們進行內核調試,以及讓我們瞭解內核的調用關係。
該函數頭文件爲:
#include <asm/ptrace.h>
使用方式:
直接在想要查看的函數中添加
dump_stack();
案例:
隨便寫了一個模塊test.c,test.c代碼如下:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/ptrace.h>
void aaa(int a);
void bbb(int b);
void ccc(int c);
void aaa(int a)
{
int b = a + 10;
bbb(b);
}
void bbb(int b)
{
int c = b + 10;
ccc(c);
}
void ccc(int c)
{
dump_stack();
printk("c is %d\n",c);
}
static int __init my_init( void )
{
int a = 10;
aaa(a);
printk("my_init \n");
}
static void __exit my_exit(void )
{
printk("my_exit \n");
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
Makefile
ifneq ($(KERNELRELEASE),)
obj-m := test.o
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
rm -r -f .tmp_versions *.mod.c .*.cmd *.o *.symvers
endif
make編譯完成後,使用insmod插入模塊,使用dmesg打印調用信息,得到信息如下:
[ 1311.888605] Call Trace:
[ 1311.888612] [<ffffffffa001a000>] ? 0xffffffffa0019fff
[ 1311.888616] [<ffffffff816cd58e>] dump_stack+0x19/0x1b
[ 1311.888619] [<ffffffffa038c015>] ccc+0x15/0x30 [test]
[ 1311.888621] [<ffffffffa038c041>] bbb+0x11/0x20 [test]
[ 1311.888623] [<ffffffffa038c061>] aaa+0x11/0x14 [test]
[ 1311.888625] [<ffffffffa001a00e>] my_init+0xe/0x1000 [test]
[ 1311.888628] [<ffffffff81002122>] do_one_initcall+0xf2/0x1a0
[ 1311.888632] [<ffffffff810c3ef3>] load_module+0x1403/0x1c00
[ 1311.888637] [<ffffffff8134fab0>] ? ddebug_add_module+0xf0/0xf0
[ 1311.888639] [<ffffffff810c47d1>] SyS_init_module+0xe1/0x130
[ 1311.888643] [<ffffffff816dc86f>] tracesys+0xe1/0xe6
[ 1311.888645] c is 30
[ 1311.888645] my_init
可以看到在函數ccc中使用dump_stack()打印出了ccc的函數調用棧。
在內核開發中,我們可以使用dump_stack()來打印相關信息,同時在內核源碼學習中也可以用來了解函數調用關係。