对应路线图: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)
rte_eal_init在 main 之前完成 hugepage/设备初始化——断点别设太早,否则先掉进 EAL 内部。- worker lcore 是
rte_eal_remote_launch拉起的线程,每个断点只对当前 thread 生效,要thread N切过去。 - 网卡绑到 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 能在断点现场调用程序里的函数,等于在暂停的进程里加了一段只读的"诊断代码"。
三个经典崩溃的排查姿势(README 06-gdb:81-96)
| 现象 | 排查命令 | 根因方向 |
|---|---|---|
SIGSEGV in rte_eth_rx_burst | bt → p port_id → call rte_eth_dev_is_valid_port(port_id) | 端口没初始化就用 |
SIGSEGV 访问 mbuf->data | p mbuf → call rte_mempool_full(pool) | mbuf 已释放或 pool 空 |
| 程序卡死 | Ctrl-C → info threads → thread apply all bt | ring 满/空导致 busy loop |
关于 README 06-gdb:99-109 提到的 dpdk.gdb 辅助脚本:它来自旧版 DPDK 的 buildtools/gdb/。我在本机 DPDK 24.11.6 源码树里全局搜过 *.gdb,一个都没有——这个目录在 24.11 已被移除。所以直接用上面的原生 gdb 命令即可,不必折腾脚本。
🐧 内核对照
| 用户态 gdb | 内核调试 | 关键差异 |
|---|---|---|
gdb -p attach | kgdb 串口/网络代理 | 内核调试要停整个系统,代价完全不同 |
p 任意变量/call 任意函数 | kprobe/bpftrace 动态插桩 | 内核倾向"可编程探测",见 P0-07 的 bpftrace |
thread apply all bt 查卡死 | sysrq-t + crash 工具 | 思路一致:先拿所有执行流的栈 |
面试 3 问
- attach 和直接 gdb 启动怎么选? → 能 attach 就 attach:EAL 初始化(hugepage/设备)已跑完,直接从业务逻辑断起(README 06-gdb:43-47)。
- 怎么在 gdb 里看一个 mbuf 指向的包内容? →
p/x mbuf->pkt_len看长度、x/64bx mbuf->buf_addr直接吐以太头字节(README 06-gdb:61-65)。 - 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)