Linux下如何利用Kprobes跟踪C++多线程程序的内核交互

冬枫吖_7418

冬枫吖_7418

2026-09-20

511人浏览

原创

kprobes 无法直接跟踪用户态 c++ 多线程函数,因其仅作用于内核空间;应聚焦跟踪 clone、do_exit、sys_futex 等关键系统调用以分析多线程行为。

linux下如何利用kprobes跟踪c++多线程程序的内核交互

不能直接用 kprobes 跟踪用户态 C++ 多线程程序本身,kprobes 只作用于内核空间;但你可以精准跟踪它触发的系统调用、内存分配、信号处理等内核行为——这才是实际调试的关键路径。

为什么不能直接 hook C++ 函数

kprobes 是内核机制,只能探测内核函数地址或指令(如 sys_readdo_fork__alloc_pages),无法看到用户态符号(如 std::thread::joinstd::mutex::lock)。C++ 多线程逻辑运行在用户空间,其函数名、栈帧、虚表调用都未暴露给内核符号表。

常见误解是试图用 symbol_name = "pthread_create" 注册 kprobe —— 这会失败,因为该符号不在内核中;glibc 的 pthread_create 最终调用的是内核的 clone 系统调用,这才是可探测点。

  • 用户态函数名对内核不可见,register_kprobe 传入无效 symbol_name 会返回 -EINVAL
  • addr 字段必须是内核虚拟地址(如通过 kallsyms_lookup_name("SyS_clone") 获取),不能是用户态 dlopen 后的地址
  • 即使强行用 /proc/kallsyms 查到某个导出符号,也需确认它是否在 kprobes 黑名单中(如 native_write_cr4

应该跟踪哪些内核函数来反映多线程行为

一个 C++ 多线程程序在内核侧的真实交互集中在几个关键系统调用和内存路径上。与其猜“哪个函数被调了”,不如盯住这些稳定、可探测、语义明确的内核入口:

  • SyS_clone(x86_64)或 sys_clone(旧命名):每次 std::thread 构造或 pthread_create 都会经过这里;regs->rax(x86_64)含 clone flags,可区分是线程还是进程
  • do_exit:线程终止时必经,配合 current->pidcurrent->tgid 可区分主线程与工作线程退出
  • sys_futex:几乎所有 std::mutexstd::condition_variable 的阻塞/唤醒都走这里;查看 regs->rdi(uaddr)和 regs->rsi(op)能判断是 WAIT 还是 WAKE
  • __do_faulthandle_mm_fault:若线程频繁触发缺页(如大量线程各自分配小对象),可定位 NUMA 或 TLB 压力

注意:SyS_* 前缀在较新内核中已统一为 __x64_sys_*,可用 cat /proc/kallsyms | grep sys_clone 实时确认符号名。

onewo-rtlinux
onewo-rtlinux

Linux 实时编程助手。生成、审查并修改用于周期性控制任务和中断驱动程序的 C 代码。强制实施实时调度策略。

下载

如何安全获取线程上下文信息

kprobe handler 运行在中断上下文且禁用抢占,不能调用 printk 过多(尤其在高频系统调用如 sys_futex 上),更不能 sleep 或访问用户态地址。但你可以安全提取以下信息:

  • current->pidcurrent->tgid 区分线程 ID 与线程组 ID(即主线程 PID)
  • regs->rdi, regs->rsi, regs->rdx 读取系统调用前三个参数(x86_64 ABI)
  • 避免直接解引用用户地址(如 *(int*)regs->rdi),可能引发 page fault 并触发 fault_handler
  • 若需记录调用栈,用 dump_stack(),但仅限调试阶段;生产环境改用 trace_printk()(写入 ftrace buffer,开销更低)

示例片段(在 handler_pre 中):

static int handler_pre(struct kprobe *p, struct pt_regs *regs) {
    if (p->symbol_name && !strcmp(p->symbol_name, "__x64_sys_clone")) {
        printk(KERN_INFO "clone: tgid=%d pid=%d flags=0x%lx\n",
               current->tgid, current->pid, regs->rsi);
    }
    return 0;
}

比手写模块更实用的替代方案

除非你要做寄存器级篡改或精确测量单条指令延迟,否则不建议从零写 kprobe 内核模块。现代内核提供了更安全、更易用的封装:

  • perf probe 快速插桩:perf probe -a 'SyS_clone:0 flags=+0(%si):x64',然后 perf record -e probe_SyS_clone ./myapp
  • 用 ftrace 的 debugfs 接口:echo 'p:clone_probe SyS_clone flags=+0(%si)' > /sys/kernel/debug/tracing/kprobe_events,再启用并抓 /sys/kernel/debug/tracing/trace
  • 结合 bpftrace 做条件过滤:例如只跟踪某进程 ID 下的 futex 调用:bpftrace -e 'kprobe:sys_futex /pid == 1234/ { printf("futex op %d\n", arg1); }'

这些方式自动处理符号解析、事件注册/卸载、输出格式化,且支持用户态进程过滤,比 raw kprobe 模块更适合多线程场景下的快速诊断。

真正容易被忽略的是:kprobe handler 里修改 regs->ip 会导致后续执行跳转,而多线程环境下这种跳转极易破坏栈平衡或 TLS 访问;除非你明确在模拟 syscall 返回或实现拦截,否则永远不要碰 regs->ip

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2068

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

939

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

367

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

307

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

346

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

560

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1389

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1177

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1305

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ 手册教程
C++ 手册教程

共41课时 | 77.9万人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习