用Bpftrace去透视Linux内核

系统 Linux
如果我们想看看tcp发送数据的大小,我们需要获取第三个(arg2)参数size的值。我们尝试写一个bpftrace的小脚本看一下size的值。

bpftrace是基于bpf实现的追踪工具,之前的文章的分享过bpftool,bpftrace的功能更加强大。

在内核中tcp发送数据是通过tcp_sendmsg 方法实现的

int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);

如果我们想看看tcp发送数据的大小,我们需要获取第三个(arg2)参数size的值。我们尝试写一个bpftrace的小脚本看一下size的值。

执行效果如下:

# bpftrace -e 'k:tcp_sendmsg { @size
Attaching 2 probes...


@size:
[1] 6 | |
[2, 4) 0 | |
[4, 8) 0 | |
[8, 16) 0 | |
[16, 32) 110 |@@@@@@@@ |
[32, 64) 687 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64, 128) 429 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[128, 256) 60 |@@@@ |
[256, 512) 96 |@@@@@@@ |
[512, 1K) 46 |@@@ |
[1K, 2K) 28 |@@ |
[2K, 4K) 8 | |
[4K, 8K) 10 | |

可以看到size的直方图,可以看到类似正态分布。

如果你想看看都是哪些进程大量发送数据,可以添加大于 1024 字节过滤器,如下:

# bpftrace -e 'k:tcp_sendmsg /arg2 > 1024/ { printf("PID %d,COMM: %s: %d bytes\n", pid,comm, arg2); }'
Attaching 1 probe...
PID 63700,COMM: kube-apiserver: 1581 bytes
PID 68206,COMM: etcd: 1079 bytes
PID 1784,COMM: kube-scheduler: 2249 bytes
PID 63700,COMM: kube-apiserver: 1581 bytes
PID 63700,COMM: kube-apiserver: 5811 bytes
PID 63700,COMM: kube-apiserver: 1581 byt

前面都是基于 tcp_sendmsg 的size参数去玩的,我们更进一步,看看发送数据包的内容,也就tcp_sendmsg的第一个参数。我们写这样一段脚本

#!/usr/local/bin/bpftrace 
#include <net/sock.h>
k:tcp_sendmsg
{
@sk[tid] = arg0;
@size[tid] = arg2;
}

kr:tcp_sendmsg
/@sk[tid]/
{
$sk = (struct sock *)@sk[tid];
$size = @size[tid];
$af = $sk->__sk_common.skc_family;
if ($af == AF_INET) {
$daddr = ntop($af, $sk->__sk_common.skc_daddr);
$saddr = ntop($af, $sk->__sk_common.skc_rcv_saddr);
$lport = $sk->__sk_common.skc_num;
$dport = $sk->__sk_common.skc_dport;
$dport = ($dport >> 8) | (($dport << 8) & 0xff00);
printf("%-15s %-5d -> %-15s %-5d: %d bytes, retval %d\n",
$saddr, $lport, $daddr, $dport, $size, retval);
} else {
printf("IPv6...\n");
}
delete(@sk[tid]);
delete(@size[tid]);
}

这段脚本有点多,初学者可能有点懵,我稍微解释一下,脚本有两个挂载点,k代表kprobe,kr代表kretprobe。脚本通过解析 sk 这个结构体,去获取tcp 包源IP和端口、目的IP和端口,这里稍微需要了解一下内核的基础数据结构体。retval 代表tcp_sendmsg 函数返回值,这个bpftrace原生支持的。

执行这个脚本

127.0.0.1       2379  -> 127.0.0.1       1236 : 64 bytes, retval 64
127.0.0.1 1236 -> 127.0.0.1 2379 : 51 bytes, retval 51
127.0.0.1 2379 -> 127.0.0.1 1236 : 38 bytes, retval 38
10.133.18.121 65286 -> 10.133.18.121 6443 : 257 bytes, retval 257

是不是非常有意思,我们基于这些数据生成每个节点之间的网络关系。

责任编辑:武晓燕 来源: 今日头条
相关推荐

2022-03-03 18:18:53

BPF解释器系统

2021-09-29 09:50:41

Linux内核日志

2021-09-08 05:46:51

Linux内核日志

2021-07-07 08:00:00

Linux开发虚拟机

2017-04-26 13:47:32

Java

2021-07-30 20:34:28

LinuxFedorabpftrace

2009-07-27 08:50:29

2022-01-24 16:42:48

bpftraceLinux工具

2021-02-20 06:08:07

LinuxWindows内核

2010-03-02 09:17:32

Linux local

2011-03-31 12:48:04

cactiLinuxWindows

2011-03-25 15:01:25

Cacti监控Windows

2011-04-02 11:12:48

cacti监控windows

2018-05-18 09:07:43

Linux内核内存

2013-11-07 13:59:56

Linux内核

2013-11-25 14:07:11

Linux内核内核特性

2021-05-19 07:56:26

Linux内核抢占

2013-11-05 09:58:39

Linux内核

2013-11-06 13:03:10

Linux内核

2013-11-12 11:01:46

Linux内核
点赞
收藏

51CTO技术栈公众号