有人质疑我ebpf水平

哈喽,我是子牙老师,一个手写过操作系统、编程语言、Java虚拟机、docker、Ubuntu系统,玩透Windows内核、Linux内核...立志一统计算机底层培训的硬核男人

不是做了一个ebpf的小课《手写生产级ebpf内存检测工具》吗,这两天不是在招生吗,质疑的声音出来了:质疑我对ebpf的认知、质疑跟着我是否能学到ebpf的真本事...

我不太喜欢向别人证明什么,相信你的人无需证明,不相信你的人,你都能佩服ta挑刺的能力!(看雷总直播拆车,小米股价跌成啥样了)刚好这两天在研究ebpf的底层实现原理,分享一下

如果想监测一个程序是否有内存泄漏,要怎么使用ebpf解决呢?监测分配内存的函数如malloc、calloc、realloc、mmap,再监测内存释放函数如free、munmap,程序退出之前,查看还有没有内存未释放,未释放的,就是泄漏的内存

如何监测呢?如果是用户态,ebpf提供了两个技术:uprobe、uretprobe,uprobe用于监测函数进入,用于拿函数传参,uretprobe用于监测函数退出,用于拿函数返回值,差不多是这个感觉

代码长这样

第一个问题来了:执行malloc函数的时候,是怎么执行到uprobe的?同样的,malloc函数结束的时候,是怎么执行到uretprobe的?

ebpf的代码是在Linux内核中的BPF虚拟机中运行的,第二个问题来了:uprobe malloc与uretprobe malloc是如何与Linux内核中的ebpf程序关联上的?

这两个问题搞明白了,ebpf你就算真正玩明白了!

我画了一张非常形象的图,所有的答案都在其中,我来给大家解释解释

以下,enjoy

第一个问题

第一个问题,执行malloc函数,是如何执行到uprobe的?采用插桩的方式。核心代码长这样

那什么是插桩呢?其实跟调试器下断点是一样的,把函数的第一个字节改成0xCC,对应的汇编指令是int3,对应的是3号软中断。对,你没有看错,插桩就是gdb调试器的断点

你现在肯定有一个问题:int3既是gdb调试器的断点,又是ebpf的插桩,发生中断,Linux内核如何区分是gdb还是ebpf呢?好问题,等下讲。你可以先想一想:如果你来设计Linux内核,你会怎么处理?

如何证明插桩的就是int3呢?看代码呗

在57536进程中的malloc上插桩

通过gdb attach到这个进程,看malloc函数的机器码

你会发现第一个字节没有被改成0xCC,但是你查看插桩,确实插桩成功了

怎么回事?理论错了?我起始也是这样的反应。如果不会玩Linux内核,到此就束手无策了,可是我会玩Linux内核啊,经单步调试Linux内核,理论没错(等下单步调试Linux内核证明给你看)

那是怎么回事呢?问ChatGPT,原来是新内核对uprobes底层做了改进

真相大白!运行时Linux内核检测到malloc是监测点,临时插入断点,触发异常,用完就恢复,所以插桩是看不到的。按照ChatGPT的说法,老版本能看到,我抽空测试一下

这个触发异常,就是第二个问题的答案

第二个问题

先上图,再聊,不然太抽象了

一、运行时Linux内核检测到malloc是监测点,临时插入断点,就是把malloc函数的第一个机器码0xf3改成0xcc,0xcc对应的汇编指令是int3,CPU执行0xcc就会触发3号软中断

二、Linux内核处理软中断的例程是do_int3

0xcc,既是gdb断点,又是ebpf插桩,Linux内核如何区分呢?

其实Linux内核也没做区分,Linux内核中有个die_notifier链,3号异常来了,先丢给优先级最高的notifier处理,ebpf插桩的优先级比gdb断点要高

比ebpf插桩优先级更高的是:kprobes、kgdb

如果触发3号异常的是ebpf插桩,就是进入arch_uprobe_exception_notify

这里最重要的一部就是打上标记,最终执行uprobe代码是在返回用户态的路上做的

找到核心代码handler_chain,下断点,看代码是不是走到这

追踪执行完uprobe程序,直接返回用户态,就是图中的3

至此,ebpf的底层实现原理,揭晓完工!撒花...

我为什么能随便玩这些,我觉得是我做了这三个课程的效用:手写64位多核操作系统+实战Linux内核+手写Ubuntu Linux系统。如果你也想像我一样,随便玩Linux内核,或者说任何技术,可以抽空把这三门课学会,加上AI的加持,计算机世界里,想干啥就可以干啥!

如果你想更多了解我,欢迎去我公众号【硬核子牙】看我之前的文章及我的奋斗历程。白手起家程序员的职场心得,应该会对你有很大启发

若有收获,就点个赞吧

相关推荐
Coder个人博客1 天前
Linux6.19-ARM64 mm mmu子模块深入分析
大数据·linux·车载系统·系统架构·系统安全·鸿蒙系统
Doro再努力1 天前
Vim 快速上手实操手册:从入门到生产环境实战
linux·编辑器·vim
wypywyp1 天前
8. ubuntu 虚拟机 linux 服务器 TCP/IP 概念辨析
linux·服务器·ubuntu
Doro再努力1 天前
【Linux操作系统10】Makefile深度解析:从依赖推导到有效编译
android·linux·运维·服务器·编辑器·vim
senijusene1 天前
Linux软件编程:IO编程,标准IO(1)
linux·运维·服务器
忧郁的橙子.1 天前
02-本地部署Ollama、Python
linux·运维·服务器
醇氧1 天前
【linux】查看发行版信息
linux·运维·服务器
No8g攻城狮1 天前
【Linux】Windows11 安装 WSL2 并运行 Ubuntu 22.04 详细操作步骤
linux·运维·ubuntu
XiaoFan0121 天前
免密批量抓取日志并集中输出
java·linux·服务器
souyuanzhanvip1 天前
ServerBox v1.0.1316 跨平台 Linux 服务器管理工具
linux·运维·服务器