本文转载,版权归作者所有。商业转载请联系作者授权,非商业转载请注明出处。作者:宋宝华来源:微信公众号linux代码阅读领域(id:linuxdev)Ftrace简介Ftrace是最有效的Linux代码级实战分析工具之一。比如我们进行系统调用的时候,出来的时间太长了。我们想知道时间都花在了哪里,在第一层用Ftrace跟踪时间分布。Ftrace案例写了一个proc模块,里面包含了proc的读写入口。test_proc_show()故意调用了一个kill_time()函数,kill_time()函数调用了mdelay(2)和kill_moretime()函数,这两个函数在body中调用了mdelay(2)。kill_time()函数和kill_moretime()函数前面都加上了noinline,以避免编译器进行内联优化。#include#include#include#include#include#include#include#includestaticunsignedint变量;staticstructproc_dir_entry*test_dir,*test_entry;staticnoinlinevoidkill_moretime(void){mdelay(2);}staticnoinlinevoidkill_time(void){mdelay(2);kill_moretime();}staticinttest_proc_show(structseq_file*seq,void*v){unsignedint*ptr_var=seq->private;kill_time();seq_printf(seq,"%u\n",*ptr_var);返回0;}staticssize_ttest_proc_write(structfile*file,constchar__user*buffer,size_tcount,loff_t*ppos){structseq_file*seq=file->private_data;unsignedint*ptr_var=seq->private;interr;char*kbuffer;如果(!buffer||count>PAGE_SIZE-1)return-EINVAL;kbuffer=(char*)__get_free_page(GFP_KERNEL);if(!kbuffer)return-ENOMEM;err=-EFAULT;if(copy_from_user(kbuffer,buffer,count))gotoout;kbuffer[count]='\0';*ptr_var=simple_strtoul(kbuffer,NULL,10);返回计数;out:free_page((unsignedlong)buffer);返回错误;}staticinttest_proc_open(structinode*inode,structfile*file){returnsingle_open(file,test_proc_show,PDE_DATA(inode));}staticconststructfile_operationstest_proc_fops={.owner=THIS_MODULE,.open=test_proc_open,.read=seq_read,.write=test_proc_write,.llseek=seq_lseek,.release=single_release,};static__initinttest_proc_init(void){test_dir=proc_mkdir("test_dir",NULL);if(test_dir){test_entry=proc_create_data("test_rw",0666,test_dir,&test_proc_fops,&variable);if(test_entry)返回0;}返回-ENOMEM;}module_init(test_proc_init);静态__exitvoidtest_proc_cleanup(void){remove_proc_entry("test_rw",test_dir);remove_proc_entry("test_dir",NULL);}module_exit(test_proc_cleanup);MODULE_AUTHOR("巴里·宋<baohua@kernel.org>");MODULE_DESCRIPTION("procexmaple");MODULE_LICENSE("GPLv2");模块对应的Makefile如下:KVERS=$(shelluname-r)#Kernelmodulesobj-m+=proc.o#为模块编译指定标志。#EXTRA_CFLAGS=-g-O0build:kernel_moduleskernel_modules:make-C/lib/modules/$(KVERS)/buildM=$(CURDIR)modulesclean:make-C/lib/modules/$(KVERS)/buildM=$(CURDIR)cleancompileandload:$makebaohua@baohua-perf:~/develop/training/debug/ftrace/proc$$sudoinsmodproc.ko[sudo]passwordforbaohua:之后就可以读写/proc目录下的/proc/test_dir/test_rw文件了,接下来我们使用Ftrace来跟踪test_proc_show()函数。我们将启动ftrace的所有命令写入脚本function.sh:#!/bin/bashdebugfs=/sys/kernel/debugechonop>$debugfs/tracing/current_tracerecho0>$debugfs/tracing/tracing_onecho$$>$debugfs/tracing/set_ftrace_pidechofunction_graph>$debugfs/tracing/current_tracer#replacetest_proc_showbyyourfunctionnameechotest_proc_show>$debugfs/tracing/set_graph_functionecho1>$debugfs/tracing/tracing_onexec"$@"然后使用这个脚本启动cat/test_dir/test_rw,这样会跟踪ftrace下的test_proc_show()函数。#./function.shcat/proc/test_dir/test_rw0读取trace结果:#cat/sys/kernel/debug/tracing/trace>1然后用vim打开这个文件1,发现这个文件有600多行:长的我都看不清了!!如何读取Ftrace结果?如何读取Ftrace结果?答案很简单:如果是叶子函数,它会直接在函数前面显示它所花费的时间。如果是非叶函数,会等到},然后显示时间,如下图:延迟比较大的部分会有+,#特殊符号如:'$'-greater超过1秒'@'-超过100毫秒'*'-超过10毫秒'#'-超过1000微秒'!'-大于100微秒'+'-大于10微秒''-小于或等于10微秒。vimfoldsFtrace上面的Ftrace文件太大,看不清楚。我们可以用vim来折迭之,不过需要一个vim的特殊配置,我把它放了我的~目录,名字叫.fungraph-vim:"Enablefoldingforftracefunction_graphtraces.""要使用,:sourcethis查看function_graph跟踪文件时,或使用vim的"-S选项从命令行加载跟踪文件。然后,您可以“使用常用的vim折叠命令,例如“za”,来打开和关闭嵌套的”函数。关闭时,折叠将显示调用所用的总时间,“通常会出现在带有右大括号的行上。折叠”函数将不包括finish_task_switch(),因此即使通过上下文切换,折叠也应该保持“相对理智””“请注意,这几乎肯定只适用于”单CPU跟踪(例如trace-cmdreport--cpu1)。功能!FunctionGraphFoldExpr(lnum)letline=getline(a:lnum)ifline[-1:]=='{'ifline=~'finish_task_switch(){$'return'>1'endifreturn'a1'elseifline[-1:]=='}'返回's1'否则返回'='endifen功能功能!FunctionGraphFoldText()lets=split(getline(v:foldstart),'|',1)ifgetline(v:foldend+1)=~'finish_task_switch(){$'lets[2]='任务切换'elselete=split(getline(v:foldend),'|',1)lets[2]=e[2]endifreturnjoin(s,'|')endfunctionsetlocalfoldexpr=FunctionGraphFoldExpr(v:lnum)setlocalfoldtext=FunctionGraphFoldText()setlocalfoldcolumn=12setlocalfoldmethod=expr之后我们配置vim为这个模板打开之前600多行的文件1:vim-S~/.fungraph-vim1这样我们看到的是:我们可以将光标移动到第5行,按键盘上的za展开:继续展开kill_time()在第6行,按za:我们可以使用键z和a来搜索或展开Ftrace的结果最后,https://github.com/brendangre...很好的封装集成了Ftrace的功能。推荐大家使用perf-tools来使用Ftrace,效果会更好更简单。有空再聊聊perf-tools吧。更多精彩更新来袭……欢迎关注微信公众号:linux代码阅读田(id:linuxdev)