死锁的本质

死锁发生的关键条件:持有锁的线程被同一个 CPU 上的中断打断,而 ISR 又要等同一把锁。

text

时间线(单核):

线程A 正在执行 sensor_read()
├─ 持有 upper->lock(nxrmutex_lock 成功)
├─ 正在读数据...
│
│ ← GPIO 中断触发!CPU 立即跳转到 ISR
│
├─ ISR: ns412_interrupt_handler()
│ └─ notify_event()
│ └─ nxrmutex_lock(&upper->lock) ← 锁被线程A持有!
│
│ 等待锁释放... 但线程A无法恢复执行!
│ 因为 ISR 不返回,CPU 永远在 ISR 里等
│ 线程A 永远无法执行到 unlock
│
└─ 💥 死锁!
ISR 是抢占式的,它打断线程A后,在 ISR 返回之前,线程A 不可能继续执行,所以锁永远无法释放。

work_queue 为什么不死锁
work_queue(HPWORK, &priv->work, ns412_irq_worker, priv, 0) 做的事情是:把 worker 函数放到一个队列里,然后立即返回。

text

时间线(单核):

线程A 正在执行 sensor_read()
├─ 持有 upper->lock
├─ 正在读数据...
│
│ ← GPIO 中断触发!
│
├─ ISR: ns412_interrupt_handler()
│ └─ work_queue(HPWORK, ...) ← 只是入队列,立即返回!
│
│ ← ISR 返回,CPU 恢复执行线程A
│
├─ 线程A 继续执行 sensor_read()
├─ nxrmutex_unlock(&upper->lock) ← 锁释放了!
│
│ ← 内核调度,切换到 HPWORK 线程
│
├─ HPWORK 线程: ns412_irq_worker()
│ └─ notify_event()
│ └─ nxrmutex_lock(&upper->lock) ← 锁已释放,成功获取!
│ └─ ... 正常执行 ...
│ └─ nxrmutex_unlock(&upper->lock)
│
└─ ✅ 没有死锁
关键区别
ISR 直接调 notify_event ISR → work_queue → worker
notify_event 在哪执行 ISR 上下文(打断当前线程) HPWORK 线程上下文(独立线程)
ISR 做了什么 调用 nxrmutex_lock → 阻塞在 ISR 里 work_queue 入队 → 立即返回
被打断的线程能恢复吗 ❌ ISR 不返回,线程永远卡住 ✅ ISR 立即返回,线程继续执行、释放锁
worker 等锁会死锁吗 N/A ❌ 不会,它只是个普通线程,等锁时让出 CPU,锁释放后自然获取

HX9033S app 编译成功了(有 .o 和 .a),但 ns412_app 没有。问题是 新增目录后 CMake 缓存没有重新生成,需要 clean rebuild:

posted @ 2026-10-24 16:14  knock~  阅读(6)  评论(0)    收藏  举报