1.问题是有打印log的功能。我想知道在执行函数之前执行了哪些函数。2、分析应用程序中打印函数栈所需的函数backtrace(),该函数对应的头文件如下:#include1。打印调用栈相关的三个函数打印函数栈需要用到以下3个函数intbacktrace(void**buffer,intsize);function函数:用于获取当前线程的调用栈。参数:buffer:是一个指针数组,函数获取到的当前线程的调用栈会存放在buffer中。缓冲区中的指针实际上是从栈中获取的返回地址,每个栈帧都有一个返回地址。size:用于指定缓冲区中可以存储多少个void*元素。返回值:实际得到的指针个数,最大不能超过size。char**backtrace_symbols(void*const*buffer,intsize);功能:将backtrace函数得到的信息转换成字符串数组。参数:buffer:从回溯函数中获取的数组指针。size:是数组中元素的个数(回溯函数的返回值)。返回值:指向与缓冲区大小相同的字符串数组的指针。每个字符串都包含与缓冲区中相应元素相关的可打印消息。它包括函数名、函数的偏移地址和实际返回地址。注意:1.只有使用ELF二进制格式的程序才能获取函数名和偏移地址。在其他系统上,只能检索十六进制的返回地址。此外,还需要将相应的标志传递给链接器以支持函数名function,即编译选项-rdynamic。2.backtrace_symbols生成的字符串全部malloced,最后需要释放这块内存。voidbacktrace_symbols_fd(void*const*buffer,intsize,intfd)函数:backtrace_symbols_fd与backtrace_symbols函数功能相同,不同的是它不返回字符串数组给调用者,而是将结果写入文件描述符为fd中,每个函数对应一行。不需要调用malloc函数,适用于函数调用可能失败的情况。参数:fd:一般填写STDOUT_FILENO2。链接库需要在编译时加入**-rdynamic**选项。-rdynamic将flag-export-dynamic传递给支持它的目标上的ELFlinker。这指示链接器将所有符号(不仅是使用过的符号)添加到动态符号表。使用“dlopen”或允许从程序中获取回溯时需要此选项。不会打印函数名称。另外,该选项不处理静态函数,因此无法获取静态函数的符号。3.例子#include#include#include#includevoidfun1();voidfun2();voidfun3();voidprint_stacktrace();voidprint_stacktrace(){intsize=16;void*array[100];intstack_num=backtrace(array,size);char**stacktrace=backtrace_symbols(array,stack_num);backtrace_symbols_fd(array,size,STDOUT_FILENO);#if0char**stacktrace=backtrace_symbols(array,stack_num);for(inti=0;i使用方法:直接在要检查的函数中添加dump_stack();2.示例测试代码如下:hello.c1#include2#include3#include46MODULE_LICENSE("GPL");7MODULE_AUTHOR("PD");8voidaaa(inta);9voidbbb(intb);10voidccc(intc);1114voidccc(intc)15{16printk(KERN_SOH"cccc\n");17dump_stack();18printk("cis%d\n",c);19}20voidbbb(intb)21{22intc=b+10;23printk(KERN_SOH"bbbb\n");24ccc(c);25}26voidaaa(inta)27{28intb=a+10;29printk(KERN_SOH"aaaa\n");30bbb(b);31}3234staticinthello_init(void)35{36inta=10;3738aaa(a);39printk(KERN_SOH"hello_init\n");4041return0;42}43staticvoidhello_exit(void)44{45printk("hello_exit\n");46return;47}4849module_init(hello_init);//insmod50module_exit(hello_exit);//rmmodMakefileifneq($(KERNELRELEASE),)obj-m:=hello.oelseKDIR:=/lib/modules/$(shelluname-r)/buildPWD:=$(shellpwd)all:make-C$(KDIR)M=$(PWD)modulesclean:rm-f*.ko*.o*.mod.o*.symvers*.cmd*.mod.c*.orderendif编译安装模块dmesg-cmakeinsmodhello.ko【注意】root权限下运行结果可见在函数ccc中使用dump_stack()打印出ccc的函数调用栈。在内核开发中,我们可以使用dump_stack()打印相关信息,在内核源码学习中也可以通过它来了解函数调用关系。