响应式编程在嵌入式中的实践——Reactive Streams与背压
文章目录

每日一句正能量
春会来,事会顺,人会好,花会开。
不是盲目乐观,而是相信时间、相信自然规律。冬天再长也会过去,困难再大也是阶段性的。与其焦虑,不如做好当下的事,然后等待。就像种花,你无法催促它,只能浇水松土,然后相信。
一、引言:当数据流淹没嵌入式系统
嵌入式系统正面临一个前所未有的挑战:数据生产速度远超处理能力。一个 6 轴 IMU 传感器以 1kHz 的频率输出数据,ADC DMA 以 10kHz 的速度填充缓冲区,CAN 总线以 500Kbps 的速率涌入报文,而主控 MCU 的主循环可能只能以 100Hz 的频率处理这些数据。
传统的应对方案是"轮询 + 中断 + 标志位":在中断里设置标志,主循环里检查标志并处理。这种模式的缺陷显而易见:
- 中断里不能做太多事,否则影响实时性
- 主循环可能错过数据,也可能被数据淹没
- 多个数据源之间的协调靠全局变量和标志位,代码难以维护
- 内存使用不可控,缓冲区要么溢出要么浪费
响应式编程(Reactive Programming)提供了一种全新的思路:将数据视为流(Stream),用声明式的方式描述数据从产生到消费的完整链路,并通过背压(Backpressure)机制让"慢消费者"控制"快生产者"的流速。
本文将深入剖析 Reactive Streams 规范的核心原理,针对嵌入式资源受限场景进行轻量化实现,并给出完整的背压控制代码实践。
二、Reactive Streams 核心模型
2.1 四个核心接口

Reactive Streams 规范定义了四个核心接口,构成了异步非阻塞流处理的基石:
| 接口 | 职责 | 嵌入式映射 |
|---|---|---|
| Publisher | 数据生产者,负责生成并推送数据 | 传感器驱动、ADC DMA、串口接收 |
| Subscriber | 数据消费者,接收并处理数据 | 控制算法、日志记录、显示更新 |
| Subscription | 订阅关系,管理背压协商 | 流控决策器、缓冲区管理 |
| Processor | 既是 Publisher 又是 Subscriber,用于中间处理 | 滤波器、数据转换、合并操作 |
核心交互协议:
Subscriber.subscribe(Publisher) → 建立订阅关系
Publisher.onSubscribe(Subscription) → 返回Subscription
Subscriber.request(n) → 请求n个数据
Publisher.onNext(data) → 推送数据
Subscriber.onComplete() → 流结束
Subscriber.onError(error) → 错误处理
背压的本质:Subscriber 通过 request(n) 主动告知 Publisher"我还能处理 n 个数据",Publisher 根据请求量推送数据。这种"拉-推混合模型"从根本上解决了生产者-消费者速率不匹配问题。
2.2 热流与冷流
- 热流(Hot Observable):无论是否有订阅者,数据都会持续产生。如传感器采样、GPIO 中断。热流必须使用背压策略,否则必然溢出。
- 冷流(Cold Observable):只有订阅后才开始产生数据。如文件读取、配置加载。冷流天然支持背压,因为生产由消费触发。
嵌入式场景中,绝大多数数据流都是热流——传感器不因为你的主循环忙就停止采样。
三、背压策略:四种武器
3.1 策略对比

| 策略 | 原理 | 数据丢失 | 内存风险 | 适用场景 |
|---|---|---|---|---|
| BUFFER | 数据缓存到缓冲区,消费者就绪后处理 | 无 | 高(可能OOM) | 数据不可丢失,如日志、审计 |
| DROP | 丢弃无法处理的数据(最旧或最新) | 有 | 低 | 实时性优先,如控制指令 |
| LATEST | 只保留最新数据,覆盖旧数据 | 有(旧数据) | 极低(固定1个) | 状态监控,如温度显示 |
| THROTTLE | 采样/节流,均匀降低数据速率 | 有(中间数据) | 低 | 采样系统,如频谱分析 |
3.2 策略选择矩阵
/* backpressure_policy.h - 背压策略定义 */
#ifndef BACKPRESSURE_POLICY_H
#define BACKPRESSURE_POLICY_H
#include <stdint.h>
/* 背压策略类型 */
typedef enum {
BP_BUFFER = 0, /* 缓冲策略 */
BP_DROP_OLDEST, /* 丢弃最旧 */
BP_DROP_LATEST, /* 丢弃最新 */
BP_LATEST_ONLY, /* 只保留最新 */
BP_THROTTLE_SAMPLE, /* 采样节流 */
BP_THROTTLE_DEBOUNCE,/* 防抖节流 */
BP_ERROR /* 错误策略:溢出时报错 */
} BackpressurePolicy_t;
/* 策略配置 */
typedef struct {
BackpressurePolicy_t policy;
uint16_t buffer_size; /* 缓冲区大小 */
uint16_t high_watermark; /* 高水位线 (%) */
uint16_t low_watermark; /* 低水位线 (%) */
uint32_t throttle_interval_ms; /* 节流间隔 */
} BackpressureConfig_t;
/* 策略选择建议 */
static inline BackpressurePolicy_t SelectPolicyForScenario(uint8_t scenario) {
switch (scenario) {
case SCENARIO_SENSOR_LOG: return BP_BUFFER; /* 传感器日志不可丢失 */
case SCENARIO_REALTIME_CTRL: return BP_LATEST_ONLY; /* 控制指令只要最新 */
case SCENARIO_STATUS_MONITOR: return BP_LATEST_ONLY; /* 状态显示只要最新 */
case SCENARIO_AUDIO_STREAM: return BP_BUFFER; /* 音频流需完整 */
case SCENARIO_KEY_EVENT: return BP_DROP_OLDEST; /* 按键事件可丢弃旧 */
case SCENARIO_CAN_BUS: return BP_THROTTLE_SAMPLE; /* CAN报文采样 */
default: return BP_DROP_LATEST;
}
}
#endif
四、嵌入式 Reactive Streams 实现
4.1 整体架构

嵌入式 Reactive Streams 实现分为三层:
Publisher 层:将硬件数据源封装为 Publisher
AdcPublisher:ADC DMA 完成中断触发数据推送GpioPublisher:GPIO 中断触发事件推送UartPublisher:串口接收中断触发数据推送TimerPublisher:定时器周期性触发CanPublisher:CAN 接收中断触发报文推送
Processor 层:流处理操作符
Filter:数字滤波(低通、高通、卡尔曼)Map:数据转换(原始值→物理量)Buffer:批量缓冲(凑够 N 个一起处理)Merge:多流合并Window:滑动窗口(用于 FFT、统计分析)
Subscriber 层:数据消费者
MotorController:电机控制算法DisplayUpdater:显示刷新Logger:日志记录CloudUploader:云端上传
4.2 核心实现
/* reactive_streams.h - 嵌入式Reactive Streams核心接口 */
#ifndef REACTIVE_STREAMS_H
#define REACTIVE_STREAMS_H
#include <stdint.h>
#include <stdbool.h>
/* 前向声明 */
struct Subscription;
struct Publisher;
struct Subscriber;
/* 数据项 */
typedef struct {
void* data;
uint16_t len;
uint32_t timestamp;
uint32_t seq;
} StreamItem_t;
/* Subscription接口 */
typedef struct Subscription {
void (*request)(struct Subscription* self, uint32_t n);
void (*cancel)(struct Subscription* self);
/* 私有数据 */
uint32_t requested_count; /* 已请求未消费的数量 */
uint32_t delivered_count; /* 已推送的数量 */
bool cancelled;
void* private_data;
} Subscription_t;
/* Subscriber接口 */
typedef struct Subscriber {
void (*onSubscribe)(struct Subscriber* self, Subscription_t* subscription);
void (*onNext)(struct Subscriber* self, const StreamItem_t* item);
void (*onError)(struct Subscriber* self, int error_code);
void (*onComplete)(struct Subscriber* self);
/* 私有数据 */
Subscription_t* subscription;
void* private_data;
} Subscriber_t;
/* Publisher接口 */
typedef struct Publisher {
void (*subscribe)(struct Publisher* self, Subscriber_t* subscriber);
/* 私有数据 */
Subscriber_t* subscriber;
Subscription_t subscription;
void* private_data;
} Publisher_t;
/* Processor:既是Publisher又是Subscriber */
typedef struct Processor {
Publisher_t publisher;
Subscriber_t subscriber;
void* private_data;
} Processor_t;
/* 内存池节点 */
typedef struct StreamNode {
StreamItem_t item;
struct StreamNode* next;
bool in_use;
} StreamNode_t;
/* 流管理器 */
typedef struct {
StreamNode_t* pool; /* 预分配节点池 */
uint16_t pool_size;
uint16_t pool_used;
StreamNode_t* head; /* 链表头 *
StreamNode_t* tail; /* 链表尾 */
uint16_t queue_depth; /* 当前队列深度 */
BackpressureConfig_t bp_config;
uint16_t high_watermark_count;
uint16_t low_watermark_count;
} StreamManager_t;
/* API */
int ReactiveStreams_Init(StreamManager_t* mgr, uint16_t pool_size,
const BackpressureConfig_t* config);\nStreamNode_t*
StreamManager_AllocNode(StreamManager_t* mgr);
void StreamManager_FreeNode(StreamManager_t* mgr, StreamNode_t* node);
int StreamManager_Enqueue(StreamManager_t* mgr, const StreamItem_t* item);
int StreamManager_Dequeue(StreamManager_t* mgr, StreamItem_t* item);
uint16_t StreamManager_GetDepth(const StreamManager_t* mgr);
void StreamManager_ApplyBackpressure(StreamManager_t* mgr);
#endif
/* reactive_streams.c - 核心实现 */
#include \"reactive_streams.h\"
#include <string.h>
/* 初始化流管理器 */
int ReactiveStreams_Init(StreamManager_t* mgr, uint16_t pool_size,
const BackpressureConfig_t* config) {
if (!mgr || !config || pool_size == 0) return -EINVAL;
memset(mgr, 0, sizeof(StreamManager_t));
/* 预分配节点池(避免运行时malloc) */
mgr->pool = (StreamNode_t*)malloc(sizeof(StreamNode_t) * pool_size);
if (!mgr->pool) return -ENOMEM;
memset(mgr->pool, 0, sizeof(StreamNode_t) * pool_size);
mgr->pool_size = pool_size;
mgr->pool_used = 0;
/* 初始化空闲链表 */
for (uint16_t i = 0; i < pool_size - 1; i++) {
mgr->pool[i].next = &mgr->pool[i + 1];
}
mgr->pool[pool_size - 1].next = NULL;
/* 配置背压 */
memcpy(&mgr->bp_config, config, sizeof(BackpressureConfig_t));
mgr->high_watermark_count = (pool_size * config->high_watermark) / 100;
mgr->low_watermark_count = (pool_size * config->low_watermark) / 100;
Log_Info(\"ReactiveStreams initialized: pool=%u, hwm=%u, lwm=%u\",
pool_size, mgr->high_watermark_count, mgr->low_watermark_count);
return 0;
}
/* 分配节点 */
StreamNode_t* StreamManager_AllocNode(StreamManager_t* mgr) {
if (!mgr || mgr->pool_used >= mgr->pool_size) return NULL;
/* 从空闲链表取一个节点 */
StreamNode_t* node = mgr->pool;
if (!node) return NULL;
mgr->pool = node->next;
node->next = NULL;
node->in_use = true;
mgr->pool_used++;
return node;
}
/* 释放节点 */
void StreamManager_FreeNode(StreamManager_t* mgr, StreamNode_t* node) {
if (!mgr || !node) return;
node->in_use = false;
node->next = mgr->pool;
mgr->pool = node;
mgr->pool_used--;
}
/* 入队(Publisher调用) */
int StreamManager_Enqueue(StreamManager_t* mgr, const StreamItem_t* item) {
if (!mgr || !item) return -EINVAL;
/* 检查背压状态 */
if (mgr->queue_depth >= mgr->high_watermark_count) {
/* 触发背压策略 */
StreamManager_ApplyBackpressure(mgr);
/* 如果策略是ERROR,直接返回 */
if (mgr->bp_config.policy == BP_ERROR) {
Log_Error(\"Stream overflow, dropping item\");
return -EAGAIN;
}
}
/* 分配节点 */
StreamNode_t* node = StreamManager_AllocNode(mgr);
if (!node) {
/* 节点池耗尽,根据策略处理 */
switch (mgr->bp_config.policy) {
case BP_DROP_OLDEST:
/* 丢弃最旧数据,腾出空间 */
if (mgr->head) {
StreamNode_t* old = mgr->head;
mgr->head = old->next;
if (!mgr->head) mgr->tail = NULL;
StreamManager_FreeNode(mgr, old);
mgr->queue_depth--;
/* 重新分配 */
node = StreamManager_AllocNode(mgr);
}
break;
case BP_DROP_LATEST:
/* 直接丢弃最新数据 */
Log_Warn(\"Stream full, dropping latest item\");
return -EAGAIN;
case BP_LATEST_ONLY:
/* 覆盖最后一个节点 */
if (mgr->tail) {
memcpy(&mgr->tail->item, item, sizeof(StreamItem_t));
return 0;
}
break;
default:
return -ENOMEM;
}
}
if (!node) return -ENOMEM;
/* 复制数据 */
memcpy(&node->item, item, sizeof(StreamItem_t));
ode->next = NULL;
/* 加入队列尾部 */
if (mgr->tail) {
mgr->tail->next = node;
} else {
mgr->head = node;
}
mgr->tail = node;
mgr->queue_depth++;
return 0;
}
/* 出队(Subscriber调用) */
int StreamManager_Dequeue(StreamManager_t* mgr, StreamItem_t* item) {
if (!mgr || !item) return -EINVAL;
if (!mgr->head) return -EAGAIN; /* 队列为空 */
StreamNode_t* node = mgr->head;
mgr->head = node->next;
if (!mgr->head) mgr->tail = NULL;
memcpy(item, &node->item, sizeof(StreamItem_t));
StreamManager_FreeNode(mgr, node);
mgr->queue_depth--;
return 0;
}
/* 应用背压策略 */
void StreamManager_ApplyBackpressure(StreamManager_t* mgr) {
if (!mgr) return;
switch (mgr->bp_config.policy) {
case BP_THROTTLE_SAMPLE:
/* 通知Publisher降低采样率 */
Publisher_Throttle(mgr, true);
break;
case BP_BUFFER:
/* 缓冲区策略:如果已满则扩展(嵌入式不推荐)或报错 */
if (mgr->queue_depth >= mgr->pool_size) {
Log_Error(\"Buffer full, consider increasing pool size\");
}
break;
case BP_LATEST_ONLY:
/* 不需要特殊处理,入队时会自动覆盖 */
break;
default:
break;
}
/* 发布背压事件 */
if (mgr->queue_depth >= mgr->high_watermark_count) {
EventBus_Publish(EVENT_BACKPRESSURE_HIGH, mgr->queue_depth);
}
}
/* 获取队列深度 */
uint16_t StreamManager_GetDepth(const StreamManager_t* mgr) {
return mgr ? mgr->queue_depth : 0;
}
五、传感器数据流背压控制实践
5.1 完整数据链路

以 1kHz 采样率的温度传感器为例,展示完整的背压控制链路:
/* sensor_publisher.c - 传感器Publisher实现 */
#include \"reactive_streams.h\"
/* 传感器Publisher上下文 */
typedef struct {
Publisher_t base;
uint8_t sensor_id;
uint32_t sample_rate_hz;
uint32_t throttle_rate_hz;
bool throttled;
TimerHandle_t sample_timer;
StreamManager_t* stream_mgr;
} SensorPublisher_t;
/* ADC采样完成中断 */
static void OnAdcConversionComplete(ADC_HandleTypeDef* hadc) {
SensorPublisher_t* pub = GetPublisherFromAdc(hadc);
if (!pub) return;
/* 读取ADC值 */
uint16_t adc_raw = HAL_ADC_GetValue(hadc);
/* 构建数据项 */
static uint8_t data_buffer[4];
memcpy(data_buffer, &adc_raw, sizeof(adc_raw));
StreamItem_t item = {
.data = data_buffer,
.len = sizeof(adc_raw),
.timestamp = HAL_GetTick(),
.seq = pub->base.subscription.delivered_count++
};
/* 入队(可能触发背压) */
int ret = StreamManager_Enqueue(pub->stream_mgr, &item);
if (ret != 0) {
/* 背压触发,记录统计 */
g_backpressureStats.dropped_count++;
}
/* 检查是否需要启动下一次转换 */
if (!pub->throttled) {
HAL_ADC_Start_IT(hadc);
}
}
/* Publisher订阅实现 */
static void SensorPublisher_Subscribe(Publisher_t* self, Subscriber_t* subscriber) {
SensorPublisher_t* pub = (SensorPublisher_t*)self;
self->subscriber = subscriber;
/* 创建Subscription */
self->subscription.requested_count = 0;
self->subscription.delivered_count = 0;
self->subscription.cancelled = false;
self->subscription.request = SensorSubscription_Request;
self->subscription.cancel = SensorSubscription_Cancel;
self->subscription.private_data = pub;
/* 通知Subscriber */
if (subscriber->onSubscribe) {
subscriber->onSubscribe(subscriber, &self->subscription);
}
Log_Info(\"SensorPublisher %u subscribed\", pub->sensor_id);
}
/* Subscription.request实现 */
static void SensorSubscription_Request(Subscription_t* self, uint32_t n) {
SensorPublisher_t* pub = (SensorPublisher_t*)self->private_data;
self->requested_count += n;
/* 根据请求量调整采样率 */
if (self->requested_count > 20) {
/* 消费者处理能力强,可以全速采样 */
pub->throttled = false;
pub->sample_rate_hz = 1000;
} else if (self->requested_count > 10) {
/* 中等处理能力 */
pub->throttled = false;
pub->sample_rate_hz = 500;
} else {
/* 处理能力弱,节流 */
pub->throttled = true;
pub->sample_rate_hz = 100;
}
/* 重新配置定时器 */
uint32_t period_ms = 1000 / pub->sample_rate_hz;
osTimerStop(pub->sample_timer);
osTimerStart(pub->sample_timer, period_ms);
Log_Debug(\"Sensor %u: request(%u), rate=%uHz\", pub->sensor_id, n, pub->sample_rate_hz);
}
/* 创建传感器Publisher */
SensorPublisher_t* SensorPublisher_Create(uint8_t sensor_id, ADC_HandleTypeDef* hadc,
StreamManager_t* stream_mgr) {
SensorPublisher_t* pub = (SensorPublisher_t*)malloc(sizeof(SensorPublisher_t));
if (!pub) return NULL;
memset(pub, 0, sizeof(SensorPublisher_t));
pub->sensor_id = sensor_id;
pub->sample_rate_hz = 1000;
pub->throttle_rate_hz = 100;
pub->throttled = false;
pub->stream_mgr = stream_mgr;
pub->base.subscribe = SensorPublisher_Subscribe;
pub->base.private_data = pub;
/* 创建采样定时器 */
pub->sample_timer = osTimerNew(SensorPublisher_OnTimer, osTimerPeriodic, pub, NULL);
/* 注册ADC中断回调 */
RegisterAdcCallback(hadc, OnAdcConversionComplete);
return pub;
}
/* filter_processor.c - 滤波Processor实现 */
#include \"reactive_streams.h\"
/* 卡尔曼滤波Processor */
typedef struct {
Processor_t base;
/* 卡尔曼滤波参数 */
float q; /* 过程噪声 */
float r; /* 测量噪声 */
float x; /* 估计值 */
float p; /* 估计误差协方差 */
float k; /* 卡尔曼增益 */
uint32_t process_count;
} KalmanFilterProcessor_t;
/* Subscriber接口:接收上游数据 */
static void KalmanFilter_OnNext(Subscriber_t* self, const StreamItem_t* item) {
KalmanFilterProcessor_t* proc = (KalmanFilterProcessor_t*)self->private_data;
/* 解析输入数据 */
uint16_t raw_adc = *(uint16_t*)item->data;
float measurement = AdcToTemperature(raw_adc); /* ADC值转温度 */
/* 卡尔曼滤波 */
/* 预测 */
proc->p = proc->p + proc->q;
/* 更新 */
proc->k = proc->p / (proc->p + proc->r);
proc->x = proc->x + proc->k * (measurement - proc->x);
proc->p = (1 - proc->k) * proc->p;
proc->process_count++;
/* 构建输出数据 */
static float filtered_temp;
filtered_temp = proc->x;
StreamItem_t output = {
.data = &filtered_temp,
.len = sizeof(filtered_temp),
.timestamp = item->timestamp,
.seq = item->seq
};
/* 推送给下游Subscriber */
if (proc->base.publisher.subscriber &&
proc->base.publisher.subscriber->onNext) {
proc->base.publisher.subscriber->onNext(
proc->base.publisher.subscriber, &output);
}
}
/* Publisher接口:订阅下游 */
static void KalmanFilter_Subscribe(Publisher_t* self, Subscriber_t* subscriber) {
KalmanFilterProcessor_t* proc = (KalmanFilterProcessor_t*)self->private_data;
self->subscriber = subscriber;
self->subscription.request = KalmanFilter_Request;
self->subscription.cancel = KalmanFilter_Cancel;
self->subscription.private_data = proc;
if (subscriber->onSubscribe) {
subscriber->onSubscribe(subscriber, &self->subscription);
}
}
/* 创建卡尔曼滤波Processor */
KalmanFilterProcessor_t* KalmanFilterProcessor_Create(float q, float r) {
KalmanFilterProcessor_t* proc = (KalmanFilterProcessor_t*)malloc(sizeof(KalmanFilterProcessor_t));
if (!proc) return NULL;
memset(proc, 0, sizeof(KalmanFilterProcessor_t));
proc->q = q;
proc->r = r;\
proc->x = 25.0f; /* 初始温度估计 */
proc->p = 1.0f;
/* 初始化Subscriber接口 */
proc->base.subscriber.onNext = KalmanFilter_OnNext;
proc->base.subscriber.onError = KalmanFilter_OnError;
proc->base.subscriber.onComplete = KalmanFilter_OnComplete;
proc->base.subscriber.private_data = proc;
/* 初始化Publisher接口 */
proc->base.publisher.subscribe = KalmanFilter_Subscribe;
proc->base.publisher.private_data = proc;
return proc;
}
六、多流合并与背压协调
6.1 合并策略

嵌入式场景中经常需要合并多个传感器数据流:
/* merge_processor.c - 多流合并Processor */
#include \"reactive_streams.h\"
/* 合并模式 */
typedef enum {
MERGE_MODE_ZIP = 0, /* 同步对齐:等待所有流同序号数据 */
MERGE_MODE_COMBINE_LATEST, /* 最新值:任一更新即触发 */
MERGE_MODE_MERGE /* 交错合并:保持时序 */
} MergeMode_t;
/* 合并Processor上下文 */
typedef struct {
Processor_t base;
MergeMode_t mode;
/* 输入流 */
#define MAX_INPUT_STREAMS 4
struct {
Subscriber_t subscriber; /* 作为Subscriber接收上游 */
StreamItem_t latest_item;
bool has_data;
uint32_t last_seq;
} inputs[MAX_INPUT_STREAMS];
uint8_t input_count;
/* 同步对齐缓冲区(Zip模式) */
StreamItem_t zip_buffer[MAX_INPUT_STREAMS];
uint32_t zip_target_seq;
/* 输出 */
Publisher_t* output_pub;
} MergeProcessor_t;
/* 输入流Subscriber的onNext */
static void MergeInput_OnNext(Subscriber_t* self, const StreamItem_t* item) {
/* 找到对应的输入槽 */
MergeProcessor_t* proc = NULL;
uint8_t input_idx = 0;
for (uint8_t i = 0; i < MAX_INPUT_STREAMS; i++) {
if (&proc->inputs[i].subscriber == self) {
proc = (MergeProcessor_t*)self->private_data;
input_idx = i;
break;
}
}
if (!proc) return;
switch (proc->mode) {
case MERGE_MODE_COMBINE_LATEST:
/* 更新最新值并立即触发 */
memcpy(&proc->inputs[input_idx].latest_item, item, sizeof(StreamItem_t));
proc->inputs[input_idx].has_data = true;
MergeProcessor_CombineLatest(proc);
break;
case MERGE_MODE_ZIP:
/* 缓存数据,等待所有流对齐 */
if (item->seq == proc->zip_target_seq) {
memcpy(&proc->zip_buffer[input_idx], item, sizeof(StreamItem_t));
proc->inputs[input_idx].has_data = true;
MergeProcessor_CheckZipComplete(proc);
}
break;
case MERGE_MODE_MERGE:
/* 直接转发,保持时序 */
MergeProcessor_Forward(proc, item);
break;
}
}
/* CombineLatest:合并各流最新值 */
static void MergeProcessor_CombineLatest(MergeProcessor_t* proc) {
/* 检查是否所有流都有数据 */
for (uint8_t i = 0; i < proc->input_count; i++) {
if (!proc->inputs[i].has_data) return;
}
/* 构建合并数据包 */
static EnvDataPacket_t packet;
packet.temp = *(float*)proc->inputs[0].latest_item.data;
packet.humidity = *(uint16_t*)proc->inputs[1].latest_item.data;
packet.pressure = *(uint32_t*)proc->inputs[2].latest_item.data;
packet.timestamp = HAL_GetTick();
StreamItem_t output = {
.data = &packet,
.len = sizeof(packet),
.timestamp = packet.timestamp,
.seq = proc->inputs[0].latest_item.seq
};
/* 推送给下游 */
if (proc->base.publisher.subscriber &&
proc->base.publisher.subscriber->onNext) {
proc->base.publisher.subscriber->onNext(
proc->base.publisher.subscriber, &output);
}
}
/* 背压协调:取最慢流速 */
static void MergeProcessor_CoordinateBackpressure(MergeProcessor_t* proc) {
/* 找到最小的request_count */
uint32_t min_request = 0xFFFFFFFF;
for (uint8_t i = 0; i < proc->input_count; i++) {
if (proc->inputs[i].subscriber.subscription &&
proc->inputs[i].subscriber.subscription->requested_count < min_request) {
min_request = proc->inputs[i].subscriber.subscription->requested_count;
}
}
/* 向上游传播背压 */
for (uint8_t i = 0; i < proc->input_count; i++) {
if (proc->inputs[i].subscriber.subscription) {
proc->inputs[i].subscriber.subscription->requested_count = min_request;
}
}\
Log_Debug(\"Merge backpressure coordinated: min_request=%u\", min_request);
}
七、HarmonyOS 集成:分布式流处理
在 HarmonyOS 分布式场景中,Reactive Streams 可以跨设备运行:
/* harmonyos_distributed_stream.c */
#include \"softbus_bus_center.h\"
#include \"reactive_streams.h\"
/* 分布式Publisher:将本地数据流发布到网络 */
typedef struct {
Publisher_t base;
char peer_device_id[64];
char channel_name[32];
StreamManager_t* local_mgr;
} DistributedPublisher_t;
/* 本地数据入队时,同时发送到远端 */
static int DistributedPublisher_Enqueue(DistributedPublisher_t* pub,
const StreamItem_t* item) {
/* 本地入队 */
int ret = StreamManager_Enqueue(pub->local_mgr, item);
if (ret != 0) return ret;\
/* 序列化并发送到远端 */
uint8_t serialized[256];
uint16_t len = SerializeStreamItem(item, serialized, sizeof(serialized));
SoftBusMessage_t msg = {
.type = SOFTBUS_MSG_TYPE_DATA,
.channel = pub->channel_name,
.payload = serialized,
.payloadLen = len
};
return SoftBus_SendMessage(pub->peer_device_id, &msg, NULL, 0);
}
/* 分布式Subscriber:接收远端数据流 */
typedef struct {
Subscriber_t base;
char local_channel[32];
StreamManager_t* recv_mgr;
} DistributedSubscriber_t;
/* 收到远端数据 */
static void OnDistributedDataReceived(const char* from_device,
const SoftBusMessage_t* msg) {
DistributedSubscriber_t* sub = FindSubscriberByChannel(msg->channel);
if (!sub) return;
/* 反序列化 */
StreamItem_t item;
DeserializeStreamItem(msg->payload, msg->payloadLen, &item);
/* 入队 */
StreamManager_Enqueue(sub->recv_mgr, &item);
/* 触发本地处理 */
if (sub->base.onNext) {
sub->base.onNext(&sub->base, &item);
}
}
/* 跨设备背压控制 */
static void DistributedBackpressure_Control(DistributedPublisher_t* pub,
uint32_t remote_capacity) {
/* 根据远端处理能力调整本地发送速率 */
if (remote_capacity < 5) {
/* 远端处理能力弱,大幅降低采样率 */
SensorPublisher_Throttle(pub->local_pub, true, 0.1f);
} else if (remote_capacity < 20) {
/* 中等能力 */
SensorPublisher_Throttle(pub->local_pub, true, 0.5f);
} else {
/* 能力强,全速 */
SensorPublisher_Throttle(pub->local_pub, false, 1.0f);
}
}
八、性能对比与优化
8.1 Reactive Streams vs 传统轮询

| 指标 | 传统轮询 | Reactive Streams | 说明 |
|---|---|---|---|
| 实时性 | 4 | 9 | 中断驱动,数据到达立即处理 |
| CPU效率 | 3 | 9 | 无空转,按需处理 |
| 内存效率 | 5 | 7 | 预分配节点池,可控可预测 |
| 代码清晰度 | 6 | 8 | 声明式流处理,逻辑清晰 |
| 可扩展性 | 4 | 9 | 新增Processor即可扩展功能 |
| 资源可控性 | 5 | 9 | 背压机制确保资源不溢出 |
8.2 关键优化手段
/* 优化1:零拷贝数据传输 */
typedef struct {
/* 不复制数据,只传递指针 */
void* data_ptr;
uint16_t len;
bool owns_data; /* 是否拥有数据所有权 */
} ZeroCopyItem_t;
/* 优化2:批量处理减少中断频率 */
#define BATCH_SIZE 10
static void ProcessBatch(Subscriber_t* sub, StreamManager_t* mgr) {
StreamItem_t batch[BATCH_SIZE];
uint8_t count = 0;
/* 一次性取出多个数据 */
while (count < BATCH_SIZE && StreamManager_Dequeue(mgr, &batch[count]) == 0) {
count++;
}
/* 批量处理 */
if (sub->onBatch) {
sub->onBatch(sub, batch, count);
}
}
/* 优化3:内存对齐与缓存友好 */
typedef struct __attribute__((aligned(4))) {
float data[4]; /* 4通道传感器数据 */
uint32_t timestamp;
uint16_t seq;
uint16_t flags;
} AlignedStreamItem_t; /* 24字节,缓存行对齐 */
/* 优化4:编译期确定流拓扑 */
#ifdef STATIC_STREAM_TOPOLOGY
/* 编译期确定Publisher、Processor、Subscriber关系 */
/* 避免运行时动态分配和查找 */
static const StreamTopology_t g_topology = {
.publisher = &g_adcPublisher,
.processors = {&g_kalmanFilter, &g_movingAverage},
.subscriber = &g_motorController
};
#endif
九、总结
响应式编程不是"大后端"的专利,在嵌入式系统中同样具有巨大价值:
- Reactive Streams 规范提供了 Publisher-Subscriber-Subscription 的标准模型,通过
request(n)实现背压控制 - 四种背压策略(BUFFER/DROP/LATEST/THROTTLE)适配不同场景,嵌入式推荐 LATEST 和 THROTTLE
- 内存池预分配避免了运行时动态分配的碎片和失败风险
- Processor 链式处理让数据流处理像搭积木一样组合
- HarmonyOS 分布式扩展让流处理跨越设备边界,实现真正的分布式响应式系统
在 HarmonyOS 生态中,随着设备类型从单一 MCU 扩展到分布式多终端协同,Reactive Streams 提供的声明式、背压感知的流处理能力,将成为连接"海量数据"与"有限资源"的关键桥梁。
转载自:https://blog.csdn.net/u014727709/article/details/162631551
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐


所有评论(0)