linux:如何查看函數被哪些函數調用過?
#if 0
char ** stacktrace = backtrace_symbols(array, stack_num);
for (int i = 0; i < stack_num; ++i)
{
printf("%s", stacktrace[i]);
}
free(stacktrace);
#endif
}
void fun1()
{
printf("stackstrace begin:");
print_stacktrace();
}
void fun2()
{
fun1();
}
void fun3()
{
fun2();
}
int main()
{
fun3();
}
編譯運行gcc編譯時加上-rdynamic參數,通知鏈接器支持函數名功能(不加-rdynamic參數則無函數名打印):
gcc 123.c -o run -rdynamic -g
執(zhí)行結果:
4. 補充 address2line
同一個函數可以在代碼中多個地方調用,如果我們只是知道函數,要想知道在哪里調用了該函數,可以通過address2line命令來完成,我們用第2步中編譯出來的test2來做實驗(address2line的-f選項可以打出函數名, -C選項也可以demangle):
address2line
三、內核代碼中如何打印函數棧?
在Linux內核中提供了一個可以打印出內核調用堆棧的函數 dump_stack()。
該函數在我們調試內核的過程中可以打印出函數調用關系,該函數可以幫助我們進行內核調試,以及讓我們了解內核的調用關系。
1. 頭文件
該函數頭文件為:
#include <asm/ptrace.h>
使用方式:
直接在想要查看的函數中添加
dump_stack();
2. 舉例
測試代碼如下:hello.c
1 #include <linux/init.h>
2 #include <linux/module.h>
3 #include <asm/ptrace.h>
4
6 MODULE_LICENSE("GPL");
7 MODULE_AUTHOR("PD");
8 void aaa(int a);
9 void bbb(int b);
10 void ccc(int c);
11
14 void ccc(int c)
15 {
16 printk(KERN_SOH"cccc ");
17 dump_stack();
18 printk("c is %d",c);
19 }
20 void bbb(int b)
21 {
22 int c = b + 10;
23 printk(KERN_SOH"bbbb ");
24 ccc(c);
25 }
26 void aaa(int a)
27 {
28 int b = a + 10;
29 printk(KERN_SOH"aaaa ");
30 bbb(b);
31 }
32
34 static int hello_init(void)
35 {
36 int a = 10;
37
38 aaa(a);
39 printk(KERN_SOH"hello_init ");
40
41 return 0;
42 }
43 static void hello_exit(void)
44 {
45 printk("hello_exit ");
46 return;
47 }
48
49 module_init(hello_init); //insmod
50 module_exit(hello_exit);//rmmod
Makefile
ifneq ($(KERNELRELEASE),)
obj-m:=hello.o
else
KDIR :=/lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.symvers *.cmd *.mod.c *.order
endif
編譯安裝模塊
dmesg -c
make
insmod hello.ko
【注意】都在root權限下操作
結果
可以看到在函數ccc中使用dump_stack()打印出了ccc的函數調用棧。
在內核開發(fā)中,我們可以使用dump_stack()來打印相關信息,同時在內核源碼學習中也可以用來了解函數調用關系。

請輸入評論內容...
請輸入評論/評論長度6~500個字