您的位置:首页 > 运维架构 > Linux

Linux之DebugFS(一)-----------------------追踪内核函数调用

2016-01-12 22:10 671 查看
debugFS是linux为了给开发人员提供更多的内核数据,方便调试和跟踪。

在嵌入式环境中,有时候内核态的函数运行时间过长可能会导致实时性受到影响,此时我们可以利用debugfs追踪内核函数调用的功能,来跟踪哪些内核函数运行时间过长,从而找出运行过长的原因。

1.首先,我们有将debugfs挂载上,以便使用其功能。

可能通过如下命令,查看当前内核是否编译进了debugfs

[root@localhost zhangxa]# cat /proc/filesystems | grep debugfs

nodev debugfs -----------支持

[root@localhost zhangxa]#

执行mount -t debugfs nodev /sys/kernel/debug命令,将debugfs挂载到/sys/kernel/debug目录

mount成功之后,可以看到挂载目录下有很多文件,这些文件就是debugfs提供功能的接口。

[root@localhost zhangxa]# cd /sys/kernel/debug/

[root@localhost debug]# ls

bdi dynamic_debug kprobes sched_features usb xen

boot_params hid mce tracing x86

[root@localhost debug]#

2.tracing目录

进入tracing目录,这里面是关于追踪功能的接口。

查看available_trace文件,里面是当前支持追踪的功能。

[root@localhost tracing]# cat available_tracers

blk kmemtrace function_graph wakeup_rt wakeup function sysprof sched_switch initcall nop

[root@localhost tracing]#

可以看到,支持追踪function,wakeup等功能。

3.编译内核支持function追踪

如果步骤2中,你当前的内核没有function这些追踪内容,说明编译内核时,没有支持此功能。需要重新编译内核,打开这些编译选项,具体的选项如下所示:

kernel hacking -------> Tracers --------> Kernel Function Tracer

打开上面的功能即可,这里面的其它功能也可以根据需要定制。

4.使用追踪功能

tracing目录上的current_trace文件,写入要追踪的功能到此函数。

[root@localhost tracing]# echo "function" > current_tracer

[root@localhost tracing]#

我们要追踪函数调用。

然后所有的函数调用就会写到trace文件中。

可以查看trace文件,里面是所有内核的函数切换和调用时间

[root@localhost tracing]# head -10 trace

# tracer: function

#

# TASK-PID CPU# TIMESTAMP FUNCTION

# | | | | |

bash-2705 [000] 1935.402307: __vma_link_rb <-dup_mm

bash-2705 [000] 1935.402307: copy_page_range <-dup_mm

bash-2705 [000] 1935.402308: kmap_atomic <-copy_page_range

bash-2705 [000] 1935.402308: kmap_atomic_prot <-kmap_atomic

bash-2705 [000] 1935.402309: debug_kmap_atomic <-kmap_atomic_prot

bash-2705 [000] 1935.402309: native_set_pte <-kmap_atomic_prot

[root@localhost tracing]#

5.我们可以写个脚本,找出某个进程PID运行时间过长的函数。

脚本接受3个参数,第一个参数为trace文件路径,第2个参数为要跟踪的进程PID,第3个参数为函数运行间隔(大于此值的函数调用会被找出)。

#!/bin/sh

filename=$1

pid=$2

interval_time=$3

if [ "$filename" == "" ]

then

echo "specify the file!"

exit 1

fi

if [ ! -f $filename ]

then

echo "file not exists!"

fi

tmpfile="$filename"

if [ ! "${pid}" == "" ]

then

tmpfile="tmp.${pid}"

cat $filename | grep ${pid} > ${tmpfile}

fi

while read line

do

time=`echo ${line} | awk '{print $3}' | sed -n 's/://gp'`

functions=`echo ${line} | awk '{print $4,$5}'`

if [ ! "$time" == "" ]

then

interval=`echo "$time-$pretime" | bc `

result=`echo "$interval - $interval_time" | bc -q | grep -v "^-"`

if [ ! "$result" == "" ]

then

echo "$interval $prefunction--$pretime $functions--$time"

fi

fi

pretime=$time

prefunction=$functions

done < $tmpfile

rm -f $tmpfile

6.过滤函数

如果我们只想追踪某些函数的调用,比如recv,send或者调度函数,则可以向set_ftrace_filter中写入模式。

如echo "send*" > set_ftrace_filter,这样就可以只追踪某些函数。

注意:要使模式生效,需要重新启用跟踪,即先向current_trace中写入nop,然后再写入function进行重启。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: