linux内核调试追踪技术

文件源

b站地址
思维导图地址 密码:linux

如何调试linux内核?

image.png

内核调试
日志:日志采集–日志分类和处理-用户查看日志

image.png

debugfs是一种虚拟的文件系统

linux内核追踪系统之事件源

linux追踪框架之ftrace

可以实现对热点函数详细的追踪分析
执行和跟踪内核里某一个函数的调用过程

前端工具:debugfs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 实践
1、进入debugfs目录
$ cd /sys/kernel/debug/tracing
如果找不到目录,执行下列命令挂载debugfs:
$ mount -t debugfs nodev /sys/kernel/debug

2、查询支持的追踪器
$ cat available_tracers
常用的有两种:

- function 表示跟踪函数的执行;
- function_graph 则是跟踪函数的调用关系;

3、查看支持追踪的内核函数和事件。其中函数就是内核中的函数名,而事件,则是内核源码中预先定义的跟踪点。
//查看内核函数
$ cat available_filter_functions
//查看事件
$ cat available_events

4、设置追踪函数:
$ echo do_sys_open > set_graph_function

5、设置追踪器
$ echo function_graph > current_tracer
$ echo funcgraph-proc > trace_options

6、开启追踪
$ echo 1 > tracing_on

7、执行一个 ls 命令后,再关闭跟踪
$ ls
$ echo 0 > tracing_on

8、最后一步,查看跟踪结果
$ cat trace

前端工具:trace-cmd

trace-cmd是ftrace的一个封装

1
2
3
4
5
6
7
8
9
10
11
12
# 安装与使用
apt install trace-cmd
man trace-cmd

# 这两个列出来的是一样的
[root@k8s-node2 tracing]# trace-cmd list -e |wc -l
1502

[root@k8s-node2 tracing]# pwd
/sys/kernel/debug/tracing
[root@k8s-node2 tracing]# cat available_events |wc -l
1502
1
2
3
4
5
6
# 实践
1、记录
$ trace-cmd record -p function_graph -g do_sys_open -O funcgraph-proc ls

2、显示
$ trace-cmd report

linux追踪框架之perf

支持采样
通过采样找到热点函数,采样频率可以通过参数指定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@k8s-node2 ~]# apt install linux-tools-common

[root@k8s-node2 ~]# cat /sys/kernel/debug/tracing/available_events | grep receive_skb
net:netif_receive_skb_list_exit
net:netif_receive_skb_exit
net:netif_receive_skb_list_entry
net:netif_receive_skb_entry
net:netif_receive_skb
[root@k8s-node2 ~]#
[root@k8s-node2 ~]# perf list| grep receive_skb
net:netif_receive_skb [Tracepoint event]
net:netif_receive_skb_entry [Tracepoint event]
net:netif_receive_skb_exit [Tracepoint event]
net:netif_receive_skb_list_entry [Tracepoint event]
net:netif_receive_skb_list_exit [Tracepoint event]
[root@k8s-node2 ~]#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# perf record
# perf script
# perf report

# perf record -g ls
# perf script
# perf report

# perf list |grep do_sys_open
# perf probe --add do_sys_open
# perf record -e probe:do_sys_open -aR sleep 1
# perf script
# perf report

# perf trace



[root@n16 dynamic-tracing]# cat main.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

void main()
{
printf("hello, pid=%d\n", getpid());
while(1) {
printf("begin sleep...\n");
sleep(1);
}
}
[root@n16 dynamic-tracing]# gcc -o main main.c
[root@n16 dynamic-tracing]# perf stat ./main
hello, pid=3422281
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
^C./main: Interrupt

Performance counter stats for './main':

0.62 msec task-clock # 0.000 CPUs utilized
6 context-switches # 0.010 M/sec
0 cpu-migrations # 0.000 K/sec
50 page-faults # 0.080 M/sec
1,508,737 cycles # 2.425 GHz
869,282 instructions # 0.58 insn per cycle
176,507 branches # 283.740 M/sec
8,840 branch-misses # 5.01% of all branches

5.795174879 seconds time elapsed

0.000627000 seconds user
0.000080000 seconds sys

# perf top



[root@n16 perf]# cat perftest.cpp
#include <stdio.h>
#include <cmath>
#include <sys/types.h>
#include <unistd.h>
using namespace std;

void for_loop()
{
for (int i = 0; i < 1000; i++) {
for (int j = 0; j < 10000; j++) {
int x = sin(i) + cos(j);
}
}
}

void loopsmall()
{
for (int i = 0; i < 10; i++) {
for_loop();
}
}

void loopbig()
{
for (int i = 0; i < 100; i++) {
for_loop();
}
}

int main()
{
printf("pid=%d\n", getpid());
loopbig();
loopsmall();

return 0;
}
[root@n16 perf]# g++ -o perftest perftest.cpp
[root@n16 perf]# ./perftest
pid=3424465
### 新开一个shell
[root@n16 perf]# perf record -p 3424465 -a -g -F 99 -- sleep 10
Warning:
PID/TID switch overriding SYSTEM
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.096 MB perf.data (982 samples) ]
[root@n16 perf]#
[root@n16 perf]#
[root@n16 perf]# perf report



# man perf report

# man perf kmem
# perf kmem record
# perf kmem stat



[root@n16 perf]# ./main
hello, pid=3430094
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
begin sleep...
### 新开一个shell
[root@n16 perf]# perf sched record -p 3430094 -- sleep 10
[root@n16 perf]# perf sched script
[root@n16 perf]# perf sched latency
[root@n16 perf]# perf report



## 全局采样
[root@n16 perf]# perf sched record -- sleep 10
[root@n16 perf]# perf sched script
[root@n16 perf]# perf sched latency
[root@n16 perf]# perf report

linux内核调试追踪技术
http://example.com/2022/12/20/linux内核调试/linux内核调试追踪技术/
作者
ningan123
发布于
2022年12月20日
许可协议