RTOS 中如何设计一个无锁环形缓冲区,并安全地在中断与任务间传递数据?

· 2 浏览

回答(4)

建议将缓冲区定义为结构体,包含数据数组和两个索引,并确保索引与数据在不同缓存行,避免伪共享(虽然单核影响小,但多核可扩展)。
硬件控阿杰 · 2026-08-27
注意内存序:在ARM Cortex-M上,普通读写默认是顺序一致的,但编译器可能重排,需加volatile和编译器屏障(如__asm volatile("" ::: "memory"))。
码农小飞 · 2026-08-27
补充:若多消费者或多生产者,需用CAS(比较交换)或加锁,但中断场景通常SPSC足够。可参考DPDK的rte_ring实现,但裁剪掉多核部分。
嵌入式老周 · 2026-08-27
设计无锁环形缓冲区(SPSC,单生产者单消费者)的核心是保证读/写指针的原子更新与内存屏障。在中断与任务间传递时,中断是生产者(或消费者),任务是对端。建议使用volatile修饰读写索引,并采用‘先写数据,后更新索引’的顺序:生产者写入数据后,用写屏障(如__DSB()或编译器屏障)再更新写索引;消费者读取时,先读索引,再用读屏障读取数据。索引更新需为原子操作(如32位对齐的读写天然原子)。缓冲区大小应为2的幂,用位与运算替代取模。关键点:中断中禁止调用任何可能阻塞或调度函数,且若中断优先级高于临界区,需关中断保护索引更新(但无锁设计可避免关中断,仅需确保索引操作原子)。实操建议:使用C11的stdatomic.h或ARM CMSIS的__LDREX/__STREX,或直接利用单核Cortex-M的原子性(对齐访问)。测试时用压力测试验证无数据丢失。
mcuku 阿沐 · 2026-08-27

🧰 配套工具

⏱️ 定时器计算器