LFBB(无锁双段缓冲)——把 DMA/实时流处理变得不费力

 

LFBB(Lock Free Bipartite Buffer)就是一个用 C11 写的“更聪明的环形缓冲区”。它在单生产者-单消费者场景下无锁,高性能,特意为需要连续内存区(给 DMA、直接处理、避免拷贝)的场景设计。简单、轻量、无动态分配,工程里用来当数据通道再合适不过了。

LFBB 是什么(通俗说法)
传统环形缓冲区有个尴尬:写/读可能跨越缓冲尾部,导致不能一次拿到连续内存。LFBB 把缓冲区“分段”管理,能保证当有足够空间/数据时,总能返回一段连续内存给你去 DMA 或直接处理。它还维护一个“invalidate(失效)索引”来跳过那些被跳过的空洞——这样既安全又高效。

它解决了哪些痛点

  • • 想把数据交给 DMA,必须要连续内存?LFBB 可以直接给你连续块,省去中间拷贝。

  • • 想在缓冲里直接处理数据(不出队)?LFBB 支持。

  • • 读写可能失败或只处理部分数据?LFBB 的接口能告诉你用了多少,再回收或放弃。

  • • 单生产者单消费者场景里想要无锁且高吞吐?LFBB 做到了。

快速信息表

项目

描述

语言

C11(标准)

适用场景

嵌入式(含 DMA)、实时流、高性能应用

线程模型

单生产者-单消费者 无锁(lock-free)

动态分配

无(用户提供缓冲区)

许可证

MIT

获取方式

CMake FetchContent / git submodule / release 下载

如何安装与集成(实操步骤)

  • • 获取库:推荐用 CMake 的 FetchContent,或者把 repo 当 submodule 拉进来,简单直接。

  • • 编译:把库加到你的 build 中(或者直接把源码放进工程),不需要复杂依赖。

  • • 配置宏:有两个重要宏 LFBB_MULTICORE_HOSTED 和 LFBB_CACHELINE_LENGTH,根据目标平台决定是否开启缓存行对齐。

示例(伪代码)——消费者:

size_t data_available;
uint8_t *read_ptr = LFBB_ReadAcquire(&lfbb, &data_available);
if (read_ptr) {
    size_t used = DoWork(read_ptr, data_available);
    LFBB_ReadRelease(&lfbb, used);
}

生产者(与 DMA 搭配):

uint8_t *w = LFBB_WriteAcquire(&lfbb, size);
if (w) {
    StartDma(w, size);
    // DMA 完成后:
    LFBB_WriteRelease(&lfbb, size);
}

关于缓存与嵌入式的注意事项
嵌入式系统用 DMA 或多核且有缓存时,必须自己做 cache sync:要么用平台提供的 DSB、缓存失效指令,要么把该内存页设置成不缓存(MMU/MPU)。LFBB 默认不给你自动同步(太依赖平台),所以别忘了这步,不然数据会怪怪的。

另外,LFBB 不会自动对齐你的写/读边界,写入时要保证按你需要的对齐方式来做。

优缺点
优点:

  • • 无锁、高性能;适合 DMA 场景;没有动态内存;接口简单易用。
    缺点/限制:

  • • 只在单生产者-单消费者场景保证无锁性质,复杂线程模型需谨慎;

  • • 缓存同步由用户负责(嵌入式需额外工作);

  • • 不做自动对齐,使用时要留心数据边界;

  • • 如果你的场景需要多生产者或多消费者,需外部同步或改设计。

总结
LFBB 很“直接、好用”,专为那些需要连续内存、低延迟、高吞吐的场景设计,在单生产者-单消费者里表现非常棒。要是你在做嵌入式 DMA、音视频流、或者任何要减少拷贝的高频数据通道,强烈值得试试。别忘了缓存同步和对齐这些工程细节。

项目地址:https://github.com/DNedic/lfbb

 

发表评论