侧边栏壁纸
  • 累计撰写 53 篇文章
  • 累计收到 3 条评论

P0-06 · gdb 实战:调试内核与用户态程序

PacketForge
2026-08-18 / 0 评论 / 0 阅读 /
对应路线图:Phase 0 (Day 1-21) | 内核 v6.6 | 上一篇:P0-05 perf | 下一篇:P0-07 内核网络栈

一句话定位

DPDK 程序调试的特殊性在于:网卡被 DPDK 接管后内核都看不到它,gdb 是你唯一能"看见包"的窗口。断点、切线程、检查 mbuf/ring/mempool 这三板斧练熟,后面每次 segfault 排查都靠它。

DPDK 调试的特殊性(README 06-gdb:10-20)

  1. rte_eal_init 在 main 之前完成 hugepage/设备初始化——断点别设太早,否则先掉进 EAL 内部。
  2. worker lcore 是 rte_eal_remote_launch 拉起的线程,每个断点只对当前 thread 生效,要 thread N 切过去。
  3. 网卡绑到 DPDK 后 ifconfig 看不到它,但内存里的 mbuf 是真实的——gdb 看内存就是看包。

真实操作:两条进场路线 + 三组检查命令

进场(README 06-gdb:34-47):

# 方式 1:直接 gdb 启动(带 DPDK EAL 参数)
gdb --args ./my_dpdk_app -l 0-1 -n 1 --no-pci
(gdb) break main
(gdb) run

# 方式 2:attach 到运行中的进程(不用重跑 EAL 初始化)
./my_dpdk_app -l 0-1 -n 1 --no-pci   # 终端 1
gdb -p $(pidof my_dpdk_app)          # 终端 2

三板斧之一:多核切换(README 06-gdb:53-57):

(gdb) info threads        # 每个 worker lcore 是一个 pthread
(gdb) thread 2            # 切到 dpdk-worker 线程

三板斧之二:检查 mbuf 内容(README 06-gdb:59-65):

(gdb) p/x ((struct rte_mbuf *)mbuf)->pkt_len
(gdb) p/x ((struct rte_mbuf *)mbuf)->data_len
(gdb) x/64bx ((struct rte_mbuf *)mbuf)->buf_addr   # 前 64 字节 = 目的MAC+源MAC+EtherType

三板斧之三:检查 ring / mempool 状态(README 06-gdb:68-75):

(gdb) p ((struct rte_ring *)ring)->prod
(gdb) p ((struct rte_ring *)ring)->cons
(gdb) call rte_mempool_avail_count(pool)   # gdb 里直接调用 DPDK API
(gdb) call rte_mempool_in_use_count(pool)

call 这条很值钱——gdb 能在断点现场调用程序里的函数,等于在暂停的进程里加了一段只读的"诊断代码"。

gdb 调试 DPDK 程序的标准流程

三个经典崩溃的排查姿势(README 06-gdb:81-96)

现象排查命令根因方向
SIGSEGV in rte_eth_rx_burstbt → p port_id → call rte_eth_dev_is_valid_port(port_id)端口没初始化就用
SIGSEGV 访问 mbuf->datap mbuf → call rte_mempool_full(pool)mbuf 已释放或 pool 空
程序卡死Ctrl-C → info threads → thread apply all btring 满/空导致 busy loop

关于 README 06-gdb:99-109 提到的 dpdk.gdb 辅助脚本:它来自旧版 DPDK 的 buildtools/gdb/。我在本机 DPDK 24.11.6 源码树里全局搜过 *.gdb,一个都没有——这个目录在 24.11 已被移除。所以直接用上面的原生 gdb 命令即可,不必折腾脚本。

🐧 内核对照

用户态 gdb内核调试关键差异
gdb -p attachkgdb 串口/网络代理内核调试要停整个系统,代价完全不同
p 任意变量/call 任意函数kprobe/bpftrace 动态插桩内核倾向"可编程探测",见 P0-07 的 bpftrace
thread apply all bt 查卡死sysrq-t + crash 工具思路一致:先拿所有执行流的栈

面试 3 问

  1. attach 和直接 gdb 启动怎么选? → 能 attach 就 attach:EAL 初始化(hugepage/设备)已跑完,直接从业务逻辑断起(README 06-gdb:43-47)。
  2. 怎么在 gdb 里看一个 mbuf 指向的包内容? → p/x mbuf->pkt_len 看长度、x/64bx mbuf->buf_addr 直接吐以太头字节(README 06-gdb:61-65)。
  3. DPDK 程序卡住不动,第一步做什么? → Ctrl-C 后 info threads + thread apply all bt,看所有 lcore 的栈——多半是某个 ring 满/空导致的自旋(README 06-gdb:92-96)。

数据落点

perf-data/P0/06-gdb/:gdb-session.log(一次完整的三板斧会话记录)、crash-bt.txt(首个 segfault 的 backtrace 存档)。

0

评论 (0)

取消