使用数组重构责任链实现通信协议解析

在嵌入式软件中,使用数组实现责任链模式是一种高效且易于维护的设计方法。相比链表,数组实现具有内存连续、访问速度快、代码简洁等优势,非常适合资源受限且对实时性要求高的嵌入式环境

为什么在嵌入式中用数组实现责任链?

1.内存连续,缓存友好:数组在内存中是连续存储的,遍历时CPU缓存命中率高,执行效率优于链表。

2.无需动态内存分配:可以预先定义固定大小的数组,避免使用 malloc/free,降低内存碎片风险。

3.代码简洁,易于调试:使用 for 循环遍历,逻辑清晰,调试时更容易追踪执行流程。

4.适合静态配置:嵌入式系统通常在编译时确定功能模块,数组非常适合这种"静态组装、动态执行"的模式。

以串口协议解析为例,实现一个基于数组的责任链
第一步:定义统一的处理器接口

c 复制代码
// protocol_handler.h
#ifndef PROTOCOL_HANDLER_H
#define PROTOCOL_HANDLER_H

#include <stdint.h>
#include <stdbool.h>

// 处理结果
typedef enum {
    HANDLER_OK,    // 成功处理,链条终止
    HANDLER_PASS,  // 无法处理,继续下一个
    HANDLER_ERROR  // 发生错误,终止链条
} HandlerResult;

// 处理器函数类型
typedef HandlerResult (*HandlerFunc)(uint8_t* data, int len);

// 责任链最大长度
#define MAX_HANDLERS 8

// 责任链结构体
typedef struct {
    HandlerFunc handlers[MAX_HANDLERS];  // 处理器函数数组
    int count;                           // 当前处理器数量
} ProtocolChain;

// 初始化责任链
void chain_init(ProtocolChain* chain);

// 添加处理器
bool chain_add_handler(ProtocolChain* chain, HandlerFunc handler);

// 执行责任链
HandlerResult chain_execute(ProtocolChain* chain, uint8_t* data, int len);

#endif

第二步:实现责任链核心逻辑

c 复制代码
// protocol_handler.c
#include "protocol_handler.h"
#include <string.h>

// 初始化
void chain_init(ProtocolChain* chain) {
    memset(chain->handlers, 0, sizeof(chain->handlers));
    chain->count = 0;
}

// 添加处理器
bool chain_add_handler(ProtocolChain* chain, HandlerFunc handler) {
    if (chain->count >= MAX_HANDLERS) {
        return false; // 数组已满
    }
    chain->handlers[chain->count++] = handler;
    return true;
}

// 执行责任链
HandlerResult chain_execute(ProtocolChain* chain, uint8_t* data, int len) {
    for (int i = 0; i < chain->count; i++) {
        HandlerResult result = chain->handlers[i](data, len);
        if (result != HANDLER_PASS) {
            return result; // OK 或 ERROR 都终止链条
        }
    }
    return HANDLER_PASS; // 所有处理器都未处理
}

第三步:实现具体协议处理器

c 复制代码
// modbus_handler.c
#include "protocol_handler.h"
#include <stdio.h>

// 简单的CRC校验函数(示例)
static bool check_crc(uint8_t* data, int len) {
    // 实际项目中应实现真实CRC算法
    return len >= 4; // 简化判断
}

// Modbus协议处理器
HandlerResult handle_modbus(uint8_t* data, int len) {
    if (len >= 4 && data == 0x01 && check_crc(data, len)) {
        printf("Modbus frame received: ");
        for (int i = 0; i < len; i++) {
            printf("%02X ", data[i]);
        }
        printf("\n");
        // 执行Modbus命令解析...
        return HANDLER_OK;
    }
    return HANDLER_PASS; // 不是Modbus帧,交给下一个
}
c 复制代码
// custom_handler.c
#include "protocol_handler.h"
#include <stdio.h>

// 自定义协议处理器
HandlerResult handle_custom(uint8_t* data, int len) {
    if (len >= 3 && data == 0xAA) {
        printf("Custom protocol: 0x%02X 0x%02X 0x%02X\n", 
               data, data, data);
        // 处理自定义协议...
        return HANDLER_OK;
    }
    return HANDLER_PASS;
}
```<websource>source_group_web_1</websource>

#### 第四步:组装和使用责任链

```c
// main.c
#include "protocol_handler.h"
#include <stdio.h>

// 外部声明处理器
extern HandlerResult handle_modbus(uint8_t*, int);
extern HandlerResult handle_custom(uint8_t*, int);

int main() {
    ProtocolChain chain;
    
    // 1. 初始化责任链
    chain_init(&chain);
    
    // 2. 静态组装责任链(编译时确定顺序)
    chain_add_handler(&chain, handle_custom);   // 先检查自定义协议
    chain_add_handler(&chain, handle_modbus);   // 再检查Modbus
    
    // 3. 模拟串口接收数据
    uint8_t frame1[] = {0xAA, 0x01, 0x02};           // 自定义协议
    uint8_t frame2[] = {0x01, 0x03, 0x00, 0x00};     // Modbus协议
    uint8_t frame3[] = {0xFF, 0xFF, 0xFF};           // 未知协议
    
    printf("--- Processing Frame 1 ---\n");
    chain_execute(&chain, frame1, sizeof(frame1));
    
    printf("\n--- Processing Frame 2 ---\n");
    chain_execute(&chain, frame2, sizeof(frame2));
    
    printf("\n--- Processing Frame 3 ---\n");
    chain_execute(&chain, frame3, sizeof(frame3));
    
    return 0;
}

数组实现 vs 链表实现

特性 数组实现 链表实现
内存使用 静态分配,无碎片 动态分配,可能碎片化
执行效率 高(缓存友好) 较低(指针跳转)
代码复杂度 简单(for循环) 复杂(指针管理)
调试难度 容易(索引清晰) 较难(指针追踪)
扩展性 固定大小,编译时确定 运行时动态添加
适用场景 协议解析、过滤器、校验链 动态审批流、插件系统
相关推荐
@insist1231 分钟前
信息安全工程师-工控安全核心知识体系(基础篇)
网络·安全·软考·信息安全工程师·软件水平考试
sunshine88521 分钟前
费控报销的“隐形战争”:如何通过流程重构实现显性降本
重构
辉视官方38 分钟前
2026深圳校园安全新方案 | SIP网络广播对讲系统,提升应急响应与智能教学水平
网络·安全
振浩微433射频芯片38 分钟前
告别“遥控失灵”:如何评估国产433芯片在智能家居领域的可靠性?
网络·单片机·嵌入式硬件·物联网·智能家居
pengyi87101542 分钟前
HTTP代理抓包核心原理,全面读懂请求与响应数据逻辑
网络·网络协议·http
云边云科技_云网融合1 小时前
@WAN SASE 1.0 全新起航,重新定义企业网络安全边界
网络·安全·web安全
小辰记事本1 小时前
从零读懂网卡内部架构:一条数据包的硬件之旅
网络·网络协议·架构·rdma
智慧光迅AINOPOL1 小时前
如何实现全光网的简单运维
网络·全光网解决方案·全光网·校园全光网·校园全光网解决方案
这是谁的博客?1 小时前
Python 异步编程核心原理与实践深度解析
java·网络·python·协程·asyncio·异步编程
2401_873479401 小时前
跨境电商如何评估用户IP真实性?用高精度IP地址查询+IP离线库实现
网络·tcp/ip·ip