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进行重启。
在嵌入式环境中,有时候内核态的函数运行时间过长可能会导致实时性受到影响,此时我们可以利用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进行重启。
相关文章推荐
- Linux系统精讲(2.6-3.9)
- Linux内核构建系统之八
- Linux中各种终端的解释
- Linux TOP 命令详述
- Linux下各规格的磁盘操作
- linux链接--硬链接,软链接
- Linux进程间通信之管道
- Linux下设置环境变量
- linux获取命令行参数struct option
- Linux笔记整理:设置任务定时删除文件
- 解决CentOS下man 命令,没有帮助信息
- CentOS 7修改主机名【hostnamectl】
- Linux下用SSH免密码登陆其他指定主机
- Linux jdk卸载安装
- 【linux信号】10.11信号集
- Linux系统搭建SVN出现Can't connect to host '192.168.0.138':连接尝试失败
- Linux安装增强功能弹出提示[未能加载虚拟硬盘]
- Linux下忘记rootpassword怎么办?
- 21.linux字符比较和循环
- linux /sys目录下的各个子目录说明