1. 问题现象与背景分析
最近在调试杰理平台的嵌入式系统时,遇到了一个棘手的异常情况:当设备在运行过程中插入U盘并执行文件操作后,如果立即拔出U盘切换到蓝牙(BT)模式,系统会触发一个关于btencry线程创建的断言错误,导致设备死机。这个问题的复现率高达90%,严重影响了产品的用户体验和稳定性。
从技术层面来看,这个问题涉及到几个关键点:
- 存储设备的插拔检测机制
- 蓝牙协议栈的初始化流程
- 线程安全与资源竞争
- 系统状态机的切换逻辑
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 问题根因定位
2.1 线程创建失败的断言分析
通过分析崩溃时的调用栈和日志,发现断言发生在蓝牙加密线程(btencry)的创建过程中。具体表现为pthread_create返回错误码EAGAIN(资源暂时不可用),这通常意味着:
- 系统线程数达到上限
- 进程的虚拟内存不足
- 内核资源耗尽
进一步排查发现,U盘拔出时没有正确释放文件系统占用的资源,导致内存泄漏。当切换到BT模式需要创建新线程时,系统资源不足。
2.2 状态切换时序问题
更深入的分析揭示了根本原因:设备在U盘拔出后没有等待存储子系统完全卸载,就立即启动了蓝牙协议栈初始化。这两个高资源消耗的操作在时间上重叠,造成了:
- 文件系统卸载未完成,占用内存未释放
- 蓝牙协议栈已经开始加载,需要分配新资源
- 加密线程创建时系统处于过渡状态
3. 解决方案设计与实现
3.1 资源管理优化
首先需要解决资源泄漏问题:
c复制// 修改后的存储设备卸载流程
void storage_device_remove() {
// 1. 同步所有缓存数据
sync();
// 2. 卸载文件系统
umount("/mnt/usb");
// 3. 释放设备资源
usb_host_deinit();
// 4. 垃圾回收
gc_collect();
}
关键改进点:
- 显式调用sync确保数据写入完成
- 按顺序执行卸载操作
- 添加内存回收机制
3.2 状态切换流程重构
实现状态机切换的互斥保护:
c复制pthread_mutex_t mode_switch_mu
