嵌入式 Linux + 内核开发高频问题及排查

1. pstack ------ 瞬间定位进程卡死、死锁、卡住不动

作用

打印正在运行的进程的线程栈,不用打断程序,不用 gdb,1 秒看到卡在哪。

最常用命令

bash

运行

复制代码
pstack <PID>

你能看到什么?

  • 程序卡在哪个函数
  • 死锁(多个线程都在 pthread_mutex_lock)
  • 死循环
  • 阻塞在 read /write/poll /sleep

嵌入式场景

  • 应用程序卡死
  • 服务不响应
  • CPU 100%
  • 驱动阻塞导致应用卡住

pstack 是排查卡死最快工具


2. gdb ------ 应用 + 内核调试全能王(嵌入式必用)

2.1 直接 attach 正在运行的进程

bash

运行

复制代码
gdb -p <PID>

然后:

  • bt 看栈
  • info threads 看所有线程
  • thread 2 切换线程
  • p 变量 打印值

2.2 分析段错误崩溃(core dump)

bash

运行

复制代码
ulimit -c unlimited
gdb ./app core.1234

输入 bt 直接定位哪一行崩溃。

2.3 嵌入式 ARM 远程调试

bash

运行

复制代码
# 板端
gdbserver :1234 ./app

# PC端
arm-linux-gnueabihf-gdb ./app
target remote 192.168.1.10:1234

3. valgrind ------ 嵌入式用户态内存问题神器

作用

检测:

  • 内存泄漏
  • 越界读写
  • 野指针
  • use-after-free
  • 重复释放

最常用命令

bash

运行

复制代码
valgrind --leak-check=full --show-reachable=yes ./app

能直接告诉你

  • 泄漏多少字节
  • 在哪分配的
  • 哪行代码没释放

嵌入式内存问题 90% 靠它定位


4. strace ------ 看应用到底在跟内核要什么

作用

跟踪所有系统调用,应用 → 内核 的所有行为全部暴露。

最常用

bash

运行

复制代码
strace -p <PID>
strace -f ./app

能定位的问题

  • 打开文件失败
  • 驱动 ioctl 报错
  • 连接失败
  • 权限被拒绝
  • 设备节点不存在
  • 驱动卡住导致应用阻塞

strace 是 "应用和内核之间的翻译官"


5. ltrace ------ 跟踪库函数调用

bash

运行

复制代码
ltrace ./app

看:

  • malloc / free
  • pthread
  • 第三方库
  • 驱动库接口

6. lsof ------ 看进程打开了哪些文件、设备、socket

bash

运行

复制代码
lsof -p <PID>

能查:

  • 设备节点被占用
  • 驱动文件被打开
  • socket 未关闭
  • 文件句柄泄漏

7. pstack + strace + valgrind 组合实战(嵌入式最常用三连)

场景 1:程序卡死

bash

运行

复制代码
pstack <PID>   # 看卡在哪一行
strace -p <PID> # 看内核是否卡住

场景 2:段错误

bash

运行

复制代码
gdb -c core ./app
bt

场景 3:内存越来越大

bash

运行

复制代码
valgrind --leak-check=full ./app

场景 4:驱动调用异常

bash

运行

复制代码
strace -f ./app | grep ioctl

问题排查一览表

调试场景 核心工具 最常用命令 核心用途(嵌入式重点) 关键说明
系统启动/卡死(U-Boot+内核) 串口工具(minicom/xshell) minicom -s(配置串口) 查看启动日志、U-Boot/内核打印,嵌入式排错核心 必须配置正确波特率(如115200)
系统启动/卡死(U-Boot+内核) U-Boot命令 printenv/setenv/tftpboot/md/mw 修改启动参数、读写寄存器、下载内核/dtb调试 解决内核启动卡死、根文件系统挂载失败
系统启动/卡死(U-Boot+内核) dtc(设备树工具) dtc -I dts -O dtb -o xxx.dtb xxx.dts(编译);dtc -I dtb -O dts xxx.dtb(反编译) 调试设备树配置错误(compatible、reg、中断等) 配合cat /proc/device-tree/查看内核识别的设备树
系统启动/卡死(U-Boot+内核) earlyprintk 启动参数添加:earlyprintk=ttySAC0,115200 解决内核启动黑屏、无输出,开启早期打印 需内核配置CONFIG_EARLY_PRINTK=y
内核崩溃(Oops/Panic/重启) dmesg dmesg / dmesg -w / dmesg | grep -i panic 查看内核日志、Oops信息、Panic原因 核心排查内核崩溃、驱动加载失败
内核崩溃(Oops/Panic/重启) addr2line arm-linux-gnueabihf-addr2line -e vmlinux 0xffffff8000321234 将Oops中的PC地址转为具体代码行 需内核开启CONFIG_DEBUG_INFO=y
内核崩溃(Oops/Panic/重启) kdump+crash crash vmlinux vmcore 捕获内核崩溃转储,分析Panic/软锁死原因 产品级排查内核崩溃的核心工具
内核崩溃(Oops/Panic/重启) kgdb 板端:echo ttySAC0 > /sys/kernel/debug/kgdboc;PC端:arm-linux-gdb vmlinux + target remote 内核源码级调试,单步跟踪内核函数 适用于内核死机、驱动初始化异常
内核崩溃(Oops/Panic/重启) JTAG/DSTREAM 硬件调试器操作(无固定命令) 板子完全死机、无法进内核时的终极调试手段 需硬件支持,定位底层硬件/内核BUG
驱动开发(加载/中断/GPIO/总线) lsmod/insmod/rmmod/modinfo insmod xxx.ko;rmmod xxx;lsmod | grep xxx 驱动加载、卸载、查看驱动信息,排查加载失败 加载失败后用dmesg看错误码(-1/-2/-16/-22)
驱动开发(加载/中断/GPIO/总线) proc/interrupts cat /proc/interrupts;watch -n1 cat /proc/interrupts 查看中断计数、中断号,排查中断风暴、中断不触发 计数不动=未触发;暴涨=中断风暴
驱动开发(加载/中断/GPIO/总线) libgpiod(GPIO工具) gpioinfo;gpioset gpiochip0 4=1;gpioget gpiochip0 5 查看GPIO配置、设置GPIO电平,排查GPIO复用/电平问题 替代传统GPIO调试方式,嵌入式首选
驱动开发(加载/中断/GPIO/总线) I2C工具(i2cdetect等) i2cdetect -y 0;i2cdump -y 0 0x48;i2cset -y 0 0x48 0x10 0xFF 扫描I2C设备、读写I2C寄存器,排查I2C通信异常 无ACK=硬件/地址/电平问题
驱动开发(加载/中断/GPIO/总线) devmem devmem 0x12340000 32(读);devmem 0x12340000 32 0x1234ABCD(写) 直接读写物理寄存器,排查时钟、复位、引脚配置 嵌入式底层硬件调试神器,需root权限
驱动开发(加载/中断/GPIO/总线) spi-tools spi-poll;spi-read;spi-write 调试SPI总线通信,排查SPI时序、设备连接问题 与I2C工具用法类似,适配SPI外设
内存问题(泄漏/越界/OOM) valgrind(用户态) valgrind --leak-check=full --show-reachable=yes ./app 检测用户态内存泄漏、越界、野指针、use-after-free 嵌入式用户态内存问题90%靠它,需编译时开启调试信息
内存问题(泄漏/越界/OOM) kmemleak(内核态) echo scan > /sys/kernel/debug/kmemleak;cat /sys/kernel/debug/kmemleak 检测内核内存泄漏,显示泄漏大小、调用栈 需内核开启CONFIG_DEBUG_KMEMLEAK=y
内存问题(泄漏/越界/OOM) KASAN(内核态) 内核配置CONFIG_KASAN=y,启动后直接看日志 检测内核内存越界、野指针、use-after-free,直接定位代码行 内核内存问题最强工具,轻微占用性能
内存问题(泄漏/越界/OOM) top/htop/free top;free -h;ps aux --sort=-rss 查看系统内存、进程内存占用,排查OOM、内存暴涨 RES字段=进程实际占用物理内存
内存问题(泄漏/越界/OOM) slabtop/cat /proc/slabinfo slabtop;cat /proc/slabinfo | grep kmalloc 查看内核slab分配,排查内核内存泄漏(某slab持续上涨) 内核内存泄漏核心排查手段
内存问题(泄漏/越界/OOM) pmap pmap <PID> 查看进程内存分布,排查内存碎片、mmap失败 适配嵌入式内存紧张场景
CPU/性能问题(高负载/卡顿/死锁) pstack pstack <PID> 快速打印线程栈,定位进程卡死、死锁、死循环,无需打断程序 排查卡死最快工具,嵌入式首选
CPU/性能问题(高负载/卡顿/死锁) perf perf top;perf record -g -p <PID>;perf report 查看内核/用户态热点函数,排查CPU高负载、性能瓶颈 需内核开启CONFIG_PERF_EVENTS=y
CPU/性能问题(高负载/卡顿/死锁) ftrace/trace-cmd cd /sys/kernel/debug/tracing;echo function > current_tracer;cat trace 跟踪内核函数调用顺序,排查软锁死、调度延迟、函数卡死 嵌入式内核性能排查神器,轻量无侵入
CPU/性能问题(高负载/卡顿/死锁) pidstat/mpstat pidstat -u 1;mpstat -P ALL 1 按进程/线程/CPU核心查看CPU占用,定位高CPU进程/线程 排查单核CPU 100%、多核负载不均
CPU/性能问题(高负载/卡顿/死锁) cyclictest cyclictest -t 1 -p 99 测试RT-Linux实时性,排查调度延迟、优先级反转 适配实时嵌入式场景
文件系统/存储(EMMC/NAND/UBI) df/du df -h;df -i;du -sh /* 查看磁盘空间、inode占用,排查磁盘满、大文件 df -i排查inode耗尽(常见于小文件过多)
文件系统/存储(EMMC/NAND/UBI) mount/umount mount;mount -o remount,rw /;umount /mnt 查看挂载情况、重新挂载(解决根文件系统只读) 只读多为存储错误,内核自动保护
文件系统/存储(EMMC/NAND/UBI) UBI工具 ubidetach -p /dev/mtdblockX;ubiattach -p /dev/mtdblockX;ubiformat 调试UBIFS挂载、UBI卷管理、Flash坏块 适配嵌入式NAND/EMMC存储场景
文件系统/存储(EMMC/NAND/UBI) fsck fsck /dev/mmcblk0p2 检查并修复文件系统错误,排查挂载失败 修复前建议备份数据
网络问题(以太网/Wi-Fi/4G) ip/ifconfig/route ip addr;ip link;route -n;ip route 查看网卡状态、IP地址、路由表,排查网卡未启动 ip命令替代传统ifconfig,功能更全
网络问题(以太网/Wi-Fi/4G) ping/mtr/tcpdump ping xxx.xxx.xxx.xxx;mtr xxx.xxx.xxx.xxx;tcpdump -i eth0 port 8080 排查网络连通性、丢包、端口通信,抓包分析异常 tcpdump需root权限,配合wireshark分析包
网络问题(以太网/Wi-Fi/4G) ethtool ethtool eth0;ethtool -s eth0 speed 100 duplex full 查看/设置网卡速率、双工模式,排查网卡硬件问题 适配以太网调试,Wi-Fi用iwconfig/iwlist
网络问题(以太网/Wi-Fi/4G) ss/netstat ss -tulnp;netstat -tulnp;ss -s 查看端口占用、TCP连接统计,排查端口被占用、TIME_WAIT过多 ss比netstat更快,适配嵌入式轻量场景
用户态应用调试(崩溃/卡死) gdb gdb -p <PID>;gdb ./app core;bt;info threads 应用崩溃调试(core文件)、运行时调试、线程调试 远程调试:板端gdbserver,PC端交叉编译gdb连接
用户态应用调试(崩溃/卡死) strace strace -p <PID>;strace -f ./app;strace -e ioctl ./app 跟踪应用系统调用,排查文件打开失败、驱动ioctl异常、权限问题 应用与内核之间的"翻译官",定位跨层问题
用户态应用调试(崩溃/卡死) ltrace ltrace ./app;ltrace -f ./app 跟踪应用库函数调用(malloc/free/pthread等),排查库调用异常 区别于strace(只跟踪系统调用)
用户态应用调试(崩溃/卡死) lsof lsof -p <PID>;lsof | grep deleted 查看进程打开的文件、设备、socket,排查文件句柄泄漏、已删未释放文件 解决"磁盘满但找不到大文件"问题
内核高级调试 lockdep 内核配置CONFIG_LOCKDEP=y,启动后查看dmesg 检测内核锁依赖、死锁风险、锁顺序倒置 内核并发/锁问题排查核心工具
内核高级调试 regmap-debugfs cat /sys/kernel/debug/regmap/xxx/registers 查看寄存器映射,排查驱动寄存器操作异常 需内核开启CONFIG_REGMAP_DEBUGFS=y

嵌入式Linux排错万能流程

  1. 先抓串口完整日志,看是否有Oops/Panic/启动卡死;

  2. 用dmesg排查驱动加载、中断、设备树异常;

  3. top/vmstat/iostat定位CPU/内存/IO高负载;

  4. 应用卡死:pstack → strace → gdb;

  5. 应用崩溃:gdb+core → valgrind;

  6. 驱动异常:dmesg → devmem/i2cdetect → 寄存器排查;

  7. 内核崩溃:addr2line → kdump+crash → KASAN/kmemleak;

  8. 完全起不来:JTAG + U-Boot调试。

相关推荐
学编程就要猛2 小时前
JavaEE初阶:网络编程
运维·服务器·网络
hughnz2 小时前
钻井自动化案例研究
运维·自动化
ILL11IIL2 小时前
Docker容器技术
运维·docker·容器
juniperhan2 小时前
Flink 系列第4篇:Flink 时间系统与 Timer 定时器实战精讲
java·大数据·数据仓库·flink
蜡笔小新..2 小时前
Linux下Matplotlib使用Times New Roman字体的解决方案
linux·运维·matplotlib
超级大只老咪2 小时前
一维度前缀和解题通用模板(java)
java·开发语言·算法
飞yu流星2 小时前
文件压缩、文本内容、文本编辑
运维·服务器
历程里程碑2 小时前
1 . Git本地操作:版本控制 跨平台协作 仓库核心
java·开发语言·数据结构·c++·git·gitee·github
洪流之源2 小时前
图像格式转换与内存对齐详解
linux