当前位置: 首页 > java >正文

【AUTOSAR COM Eth】Service Discovery (SD) 模块技术解析

在这里插入图片描述

文章目录

    • 一、基本概念
      • 1.1 SD模块定位
      • 1.2 协议规范
      • 1.3 模块架构
    • 二、工作原理详解
      • 2.1 整体流程
      • 2.2 核心交互流程
        • 2.2.1 服务发现流程
        • 2.2.2 事件组订阅流程
    • 三、核心数据结构解析
      • 3.1 协议头结构(Sd_HeaderType)
      • 3.2 服务条目结构(Sd_Type1EntryType)
      • 3.3 事件组条目结构(Sd_Type2EntryType)
      • 3.4 会话控制结构(Sd_SessionIdCtrlType)
      • 3.5 发送队列结构(Sd_SendQueueType)
    • 四、重要函数功能解析
      • 4.1 模块初始化(Sd_Init)
      • 4.2 主处理函数(Sd_MainFunction)
      • 4.3 消息解析(Sd_ParseRxMessage)
      • 4.4 服务生命周期管理
        • 4.4.1 服务下线处理(Sd_ServerServiceDownPhaseHandle)
        • 4.4.2 初始等待处理(Sd_ServerServiceInitialWaitPhaseHandle)
      • 4.5 事件组订阅管理
        • 4.5.1 订阅处理(Sd_RxSubscribeEventgroupHandle)
        • 4.5.2 多播控制(Sd_FanOutMulticastUnicastCtrlAddClient)
    • 五、内存管理机制
      • 5.1 内存池设计
      • 5.2 内存操作函数
    • 六、网络协议处理
      • 6.1 IP地址检查(Sd_IsIpAddrInSameSubset)
      • 6.2 端点选项处理
        • 6.2.1 IPv4端点构建
        • 6.2.2 IPv6支持
    • 七、状态机实现
      • 7.1 服务器状态机
      • 7.2 客户端状态机
    • 八、错误处理机制
      • 8.1 错误报告
      • 8.2 重启处理
    • 九、应用案例分析
      • 9.1 服务发现场景
      • 9.2 事件组订阅场景
      • 9.3 网络异常处理
    • 十、性能优化措施
      • 10.1 内存分配优化
      • 10.2 状态机优化
      • 10.3 发送队列优化
    • 十一、安全机制实现
      • 11.1 选项安全检查
      • 11.2 会话ID管理
      • 11.3 重启检测
    • 十二、配置管理机制
      • 12.1 动态配置支持
      • 12.2 配置选项构建
    • 十三、版本特性实现
      • 13.1 多播发送优化
      • 13.2 会话ID管理改进
    • 十四、编译配置管理
      • 14.1 条件编译控制
      • 14.2 特性开关
    • 十五、运行时数据结构
      • 15.1 服务器运行时(Sd_ServerServiceRTType)
      • 15.2 客户端运行时(Sd_ClientServiceRTType)
    • 十六、接口函数实现
      • 16.1 服务状态设置(Sd_ServerServiceSetState)
      • 16.2 事件组状态设置(Sd_ConsumedEventGroupSetState)
    • 十七、网络适配层交互
      • 17.1 套接字管理
      • 17.2 地址分配处理
    • 十八、消息打包发送
      • 18.1 消息打包(Sd_PackageMessage)
      • 18.2 发送调度(Sd_TransmitMessage)
    • 十九、异常处理机制
      • 19.1 消息格式检查(Sd_OptionFormatCheck)
      • 19.2 消息冲突检查(Sd_OptionsConflictCheck)
    • 二十、高级特性实现
      • 20.1 会话ID管理
      • 20.2 重试机制(SD_SUBSCRIBE_EVENTGROUP_RETRY_ENABLE)
      • 20.3 路由控制
    • 二十一、典型应用场景
      • 21.1 服务发现
      • 21.2 事件组订阅
      • 21.3 网络异常恢复(续)
        • TCP连接异常恢复
        • UDP连接异常恢复
      • 21.4 消息重传机制
        • 订阅事件组重试
      • 21.5 安全检查机制
        • IP地址子网检查
      • 21.6 版本兼容性处理
        • 协议版本检查
      • 21.7 内存管理优化
        • 内存池初始化
    • 22. 应用案例分析
      • 22.1 车载娱乐系统服务发现
      • 22.2 自动驾驶系统的事件组订阅
      • 22.3 网络拓扑变化处理
    • 23. 模块优势与局限性
      • 23.1 优势分析
      • 23.2 局限性探讨
    • 24. 未来优化方向
      • 24.1 IPv6全面支持
      • 24.2 内存管理优化
      • 24.3 错误恢复增强
    • 25. 总结

一、基本概念

1.1 SD模块定位

Service Discovery(SD)模块是AUTOSAR架构中负责服务发现的核心组件,作为SOME/IP协议栈的关键组成部分,主要实现以下功能:

  • 服务生命周期管理(Offer/StopOffer)
  • 事件组订阅控制(Subscribe/Unsubscribe)
  • 网络地址转换与路由控制
  • 会话ID管理
  • 异常消息处理

1.2 协议规范

本模块严格遵循:

  • AUTOSAR Classic Platform R19-11规范
  • SOME/IP-SD协议标准
  • TCP/IP协议族规范(IPv4为主)

1.3 模块架构

模块采用分层设计:

+-----------------------+
|   应用接口层          |
| (BswM/Sd_User)        |
+-----------------------+
|   协议解析层          |
| (Sd_ParseRxMessage)   |
+-----------------------+
|   服务管理层          |
| (Sd_ServerService...) |
+-----------------------+
|   事件组管理层        |
| (Sd_EventHandler...) |
+-----------------------+
|   网络适配层          |
| (SoAd集成)            |
+-----------------------+
|   内存管理层          |
| (MemHeap自定义实现)    |
+-----------------------+

二、工作原理详解

2.1 整体流程

模块工作周期分为四个阶段:

                          +-----------------+|  初始化阶段       || (SD_INIT)        |+--------+--------+|+-------------------------v--------------------------+|  +------------------+   +------------------+      ||  | 服务器服务处理    |   | 客户端服务处理    |      ||  | (ServerService)  |   | (ClientService)   |      ||  +--------+--------+   +--------+--------+   +---v---+|           |                     |           | 消息发 ||           |                     |           | 送处理 ||  +--------v--------+   +--------v--------+   +---+---+|  | 事件组处理        |   | 事件组订阅处理    |       ||  | (EventHandler)    |   | (ConsumedEvent)   |       ||  +------------------+   +------------------+       |+-------------------------+--------------------------+

2.2 核心交互流程

2.2.1 服务发现流程
Client SD模块 Server SoAd Sd_ClientServiceSetState(REQUESTED) SoAd_OpenSoCon() 发送FindService消息 回复OfferService 通知服务可用 建立TCP/UDP连接 Client SD模块 Server SoAd
2.2.2 事件组订阅流程
Client SD Server SoAd Sd_ConsumedEventGroupSetState(REQUESTED) 发送SubscribeEventGroup 回复SubscribeAck 建立多播路由 通知事件组可用 Client SD Server SoAd

三、核心数据结构解析

3.1 协议头结构(Sd_HeaderType)

typedef struct {uint16 ClientID;          // 客户端标识uint16 SessionID;        // 会话IDuint8 ProtocolVersion;   // 协议版本(固定0x01)uint8 InterfaceVersion;  // 接口版本(固定0x01)uint8 MessageType;       // 消息类型(固定0x02)uint8 ReturnCode;        // 返回码(固定0x00)union {struct {uint8 RebootFlag : 1;    // 重启标志uint8 UnicastFlag : 1;   // 单播标志};struct {uint8 Reserved : 6;      // 保留位};};uint8 Reserved[3];       // 保留字段
} Sd_HeaderType;

内存布局特性

  • 支持大小端自适应
  • 包含必要的协议元数据
  • 会话ID管理支持单播/多播独立计数

3.2 服务条目结构(Sd_Type1EntryType)

typedef struct {uint8 Type;               // 条目类型uint8 Index1stOptions;   // 第一个选项索引uint8 Index2ndOptions;   // 第二个选项索引union {struct {uint8 NumOfOpt1 : 4;    // 选项1数量uint8 NumOfOpt2 : 4;    // 选项2数量};};uint16 ServiceID;        // 服务IDuint16 InstanceID;       // 实例IDuint8 MajorVersion;      // 主版本号uint8 TTL[3];            // 生存时间(3字节)uint32 MinorVersion;     // 次版本号
} Sd_Type1EntryType;

关键字段说明

  • TTL字段采用3字节存储,通过Sd_SetTTL进行64位扩展
  • 支持两个选项索引,实现灵活的选项引用
  • 版本号分离存储(Major/Minor)

3.3 事件组条目结构(Sd_Type2EntryType)

typedef struct {uint8 Type;               // 条目类型uint8 Index1stOptions;   // 第一个选项索引uint8 Index2ndOptions;   // 第二个选项索引union {struct {uint8 NumOfOpt1 : 4;    // 选项1数量uint8 NumOfOpt2 : 4;    // 选项2数量};};uint16 ServiceID;        // 服务IDuint16 InstanceID;       // 实例IDuint8 MajorVersion;      // 主版本号uint8 TTL[3];            // 生存时间uint8 Reserved;          // 保留字段union {struct {uint8 Counter : 4;      // 订阅计数器uint8 Reserved : 4;     // 保留位};};uint16 EventGroupID;     // 事件组ID
} Sd_Type2EntryType;

增强特性

  • 支持订阅计数器(4位)
  • 保留字段确保内存对齐
  • 支持事件组级别的TTL管理

3.4 会话控制结构(Sd_SessionIdCtrlType)

typedef struct Sd_SessionIdCtrlType_ {TcpIp_SockAddrType remoteAddr; // 远程地址uint16 txUniSesIdCnt;         // 单播会话计数uint16 rxUniSesIdCnt;         // 接收单播计数uint16 rxMultiSesIdCnt;       // 接收多播计数uint8 rxUniRebootFlag;        // 单播重启标志uint8 rxMultiRebootFlag;      // 多播重启标志Sd_ServiceHandleIdListType* serverServiceList; // 服务列表Sd_ServiceHandleIdListType* clientServiceList; // 客户端列表struct Sd_SessionIdCtrlType_* next;            // 下一个节点
} Sd_SessionIdCtrlType;

设计亮点

  • 双链表结构支持动态扩展
  • 独立维护单播/多播会话ID
  • 服务列表支持按需分配(16项为单位)

3.5 发送队列结构(Sd_SendQueueType)

typedef struct Sd_SendQueueType_ {TcpIp_SockAddrType destAddr; // 目标地址uint8* entryPtr;            // 条目指针uint8* optionPtr;           // 选项指针uint32 sendTime;            // 发送时间struct Sd_SendQueueType_* next; // 下一个节点uint16 optStartPos[3];      // 选项起始位置uint16 optionLen;           // 选项总长度uint8 optionNum;            // 选项数量boolean isUnicastSend;      // 是否单播发送
} Sd_SendQueueType;

队列管理机制

  • 支持多播/单播消息分离
  • 环形队列优化发送效率
  • 每个队列节点独立管理发送参数

四、重要函数功能解析

4.1 模块初始化(Sd_Init)

功能

  1. 配置数据验证
  2. 内存池初始化(RX/TX)
  3. 状态机初始化
  4. 套接字连接建立

关键代码段

/* 初始化内存池 */
memPoolRet = Sd_InitMemoryPool(SD_TX_MEMORY_POOL_SIZE, Sd_TxMemPool);
if (MEMHEAP_OK == memPoolRet) {initResult1 = SD_INIT_SUCCESS;
}/* 初始化IP地址状态 */
for (index = 0u; index < SD_INSTANCE_NUM; index++) {Sd_InstanceRTData[index].ipAddrState = TCPIP_IPADDR_STATE_UNASSIGNED;Sd_InstanceRTData[index].rebootFlag = TRUE;
}

4.2 主处理函数(Sd_MainFunction)

执行流程

  1. 随机种子递增
  2. 解析接收队列
  3. 服务状态机处理
  4. 事件组状态机处理
  5. 消息发送调度

性能优化

/* 随机种子递增 */
Sd_RandomSeed++;/* 解析接收消息 */
#if ((SD_SERVER_SERVICE_NUM > 0) || (SD_CLIENT_SERVICE_NUM > 0))
Sd_ParseRxMessage();
#endif/* 定时器处理 */
Sd_ServerServiceTimerHandle(instancePtr, serverServicePtr);

4.3 消息解析(Sd_ParseRxMessage)

处理流程

  1. 选项格式检查
  2. 地址有效性验证
  3. 会话ID更新
  4. 条目类型分发

安全机制

optFormatCheckRet = Sd_OptionFormatCheck(sdMsg);
if (E_OK == optFormatCheckRet) {// 选项冲突检查optConflictCheckRet = Sd_OptionsConflictCheck(sdMsg, index, optStartPos);
}// 地址子网检查
checkPass = Sd_IsIpAddrInSameSubset((uint8*)localAddr.addr,(const uint8*)ipv4Opt.IPv4Address,localAddrCheckLen,4u);

4.4 服务生命周期管理

4.4.1 服务下线处理(Sd_ServerServiceDownPhaseHandle)

处理逻辑

  1. 清理发送队列
  2. 发送StopOfferService
  3. 重置事件组订阅
  4. 路由关闭

状态迁移

if (SD_CLIENT_PHASE_MAIN == cRtDataPtr->phase) {// 清理发送队列Sd_ClearSendQueue(&cRtDataPtr->head);// 发送停止服务消息Sd_BuildOfferServiceEntry(..., TRUE);
}
4.4.2 初始等待处理(Sd_ServerServiceInitialWaitPhaseHandle)

随机延迟计算

tRandom = Sd_GetRandomValue(delayMin, delayMax);
tRandom = Sd_SendTimeAdjust(tRandom / SD_MAIN_FUNCTION_CYCLE_TIME);

4.5 事件组订阅管理

4.5.1 订阅处理(Sd_RxSubscribeEventgroupHandle)

关键检查

if ((tcpEndpointNum > 0u) && (NULL_PTR != eventHandlerPtr->SdEventHandlerTcp)) {ret = Sd_FanOutControlTCP(...);
}if ((E_OK == ret) && (udpEndpointNum > 0u) && (NULL_PTR != eventHandlerPtr->SdEventHandlerUdp)) {ret = Sd_FanOutControlUDP(...);
}
4.5.2 多播控制(Sd_FanOutMulticastUnicastCtrlAddClient)

动态路由切换

if (subscribedClientNum < threshold) {// 启用单播SoAd_EnableSpecificRouting(...);
} else if (subscribedClientNum == threshold) {// 切换为多播SoAd_EnableSpecificRouting(multiSoConId);// 禁用单播Sd_DisableUnicastForSubscribedClient(...);
}

五、内存管理机制

5.1 内存池设计

#define SD_RX_MEMORY_POOL_SIZE  // 接收池大小
#define SD_TX_MEMORY_POOL_SIZE  // 发送池大小static uint8 Sd_RxMemPool[SD_RX_MEMORY_POOL_SIZE];
static uint8 Sd_TxMemPool[SD_TX_MEMORY_POOL_SIZE];

分配策略

  • 使用ILib_MemHeap系列函数
  • 支持配置报告内存不足错误(SD_MALLOC_FAIL_REPORT_ENABLE)

5.2 内存操作函数

SD_LOCAL_INLINE void Sd_InitMemoryPool(...) {return ILib_MemHeapInit(...);
}static void* Sd_MallocEx(...) {// 支持错误报告#if ((SD_DEM_USED == STD_ON) && (SD_MALLOC_FAIL_REPORT_ENABLE == STD_ON))if (NULL_PTR == ret) {Dem_ReportErrorStatus(...);}#endif
}static void Sd_FreeEx(...) {// 线程安全释放SchM_Enter_Sd_ExclusiveArea();ILib_MemHeapFree(...);SchM_Exit_Sd_ExclusiveArea();
}

六、网络协议处理

6.1 IP地址检查(Sd_IsIpAddrInSameSubset)

子网匹配算法

cmpResult = ILib_memcmp(ipAddr1, ipAddr2, addrLen);
if (0 != cmpResult) {// 子网掩码计算netmaskArray[tAddrLen - index] = 0x00;// 按位与运算cmpResult = ILib_memcmp(addr1AndResult, addr2AndResult, addrLen);
}

6.2 端点选项处理

6.2.1 IPv4端点构建
static void Sd_SetIPv4EndpointOption(...) {ipv4Option.Length = Sd_HtoNs(SD_IPV4_ENDPOINT_OPTION_LENGTH);ipv4Option.Type = SD_IPV4_ENDPOINT_OPTION;// 设置IP地址ILib_memcpy(ipv4Option.IPv4Address, ipv4Address, 4);// 端口转换ipv4Option.PortNumber = Sd_HtoNs(portNumber);
}
6.2.2 IPv6支持
#if (STD_ON == SD_IPV6_ENABLE)
static void Sd_SetIPv6EndpointOption(...) {ipv6Option.Length = Sd_HtoNs(SD_IPV6_ENDPOINT_OPTION_LENGTH);ipv6Option.Type = SD_IPV6_ENDPOINT_OPTION;ILib_memcpy(ipv6Option.IPv6Address, ipv6Address, 16);ipv6Option.PortNumber = Sd_HtoNs(portNumber);
}
#endif

七、状态机实现

7.1 服务器状态机

typedef enum {SD_SERVER_PHASE_DOWN,         // 下线状态SD_SERVER_PHASE_INITIAL_WAIT, // 初始等待SD_SERVER_PHASE_REPETITION,  // 重复发送SD_SERVER_PHASE_MAIN         // 主状态
} Sd_ServerServicePhaseType;

状态迁移

DOWN -> INITIAL_WAIT -> REPETITION -> MAIN
^
|
+----+----+----+----+|    |    ||    |    +-- Sd_ServerServiceRepetitionPhaseHandle|    +------- Sd_ServerServiceInitialWaitPhaseHandle+------------ Sd_ServerServiceDownPhaseHandle

7.2 客户端状态机

typedef enum {SD_CLIENT_PHASE_DOWN,         // 下线状态SD_CLIENT_PHASE_INITIAL_WAIT, // 初始等待SD_CLIENT_PHASE_REPETITION,  // 重复请求SD_CLIENT_PHASE_MAIN         // 主状态
} Sd_ClientServicePhaseType;

状态处理

switch (phase) {
case SD_CLIENT_PHASE_DOWN:Sd_ClientServiceDownPhaseHandle(...);
case SD_CLIENT_PHASE_INITIAL_WAIT:Sd_ClientServiceInitialWaitPhaseHandle(...);
case SD_CLIENT_PHASE_REPETITION:Sd_ClientServiceRepetitionPhaseHandle(...);
case SD_CLIENT_PHASE_MAIN:Sd_ClientServiceMainPhaseHandle(...);
}

八、错误处理机制

8.1 错误报告

#if (STD_ON == SD_DEV_ERROR_DETECT)
#define SD_REPORT_ERROR(ApiId, ErrorId) \Det_ReportError(SD_MODULE_ID, SD_INSTANCE_ID, (ApiId), (ErrorId));
#endif#if (SD_DEM_USED == STD_ON)
void Sd_RemoteRebootDetectedHandle(...) {Dem_ReportErrorStatus(eventId, DEM_EVENT_STATUS_FAILED);
}
#endif

8.2 重启处理

static void Sd_RemoteRebootDetectedHandle(...) {// 处理服务重启for (index = 0u; index < clientServiceList->handleIdNum; index++) {Sd_RxStopOfferServiceHandle(clientServiceList->serviceHandleId[index]);}// 删除会话节点Sd_DeleteSessionIdNode(...);
}

九、应用案例分析

9.1 服务发现场景

典型交互流程

client sd soad server Sd_ClientServiceSetState(REQUESTED) SoAd_OpenSoCon() 回调Sd_LocalIpAddrAssignmentChg 发送FindService 回复OfferService BswM通知可用 SoAd_EnableSpecificRouting() client sd soad server

关键代码

void Sd_LocalIpAddrAssignmentChg(...) {for (idx = 0u; idx < SD_INSTANCE_NUM; idx++) {if (txPduSoConId == SoConId) {Sd_InstanceRTData[idx].ipAddrState = State;}}
}

9.2 事件组订阅场景

订阅流程

client sd server soad Sd_ConsumedEventGroupSetState(REQUESTED) 发送SubscribeEventGroup 回复SubscribeAck 建立多播路由 BswM通知事件组可用 client sd server soad

实现细节

static Std_ReturnType Sd_BuildSubscribeEventgroupEntry(...) {// 构建TCP/UDP选项if (tcpSoCon.isSoConOpened) {build IPv4/IPv6 Endpoint OptionSoAd_EnableSpecificRouting(tcpSoCon.soConId);}// 构建配置选项Sd_BuildType2ConfigurationOption(...);
}

9.3 网络异常处理

IP地址变更处理

void Sd_SoConModeChg(...) {if (SOAD_SOCON_ONLINE != Mode) {// 关闭连接Sd_ClientServiceCloseSoCon(...);// 进入初始等待Sd_ClientServiceInitialWaitEnter(...);}
}

重启处理

static void Sd_ServerServiceDownPhaseHandle(...) {// 清理发送队列Sd_ClearSendQueue(&sRtDataPtr->head);// 发送StopOfferSd_BuildOfferServiceEntry(..., TRUE);
}

十、性能优化措施

10.1 内存分配优化

  • 采用内存池分配器,减少碎片
  • 批量预分配服务句柄列表(16项为单位)
  • 支持编译时配置内存池大小

10.2 状态机优化

  • 使用位域优化状态存储
  • 合并重复检查逻辑(如Sd_IsIpAddrInSameSubset)
  • 减少不必要的内存拷贝

10.3 发送队列优化

static void Sd_TransmitMessage(void) {for (instanceIdx = 0u; instanceIdx < SD_INSTANCE_NUM; instanceIdx++) {// 优先发送单播uniSendCnt = Sd_FindoutUnicastMessage(...);if (uniSendCnt > 0u) {Sd_TransmitUnicastMessage(...);}// 后发送多播multiSendCnt = Sd_FindoutMulticastMessage(...);if (multiSendCnt > 0u) {Sd_TransmitMulticastMessage(...);}}
}

十一、安全机制实现

11.1 选项安全检查

static Std_ReturnType Sd_OptionsSecurityCheck(...) {// 子网检查checkPass = Sd_IsIpAddrInSameSubset(...);// 选项冲突检查Sd_OptionsConflictCheck(...);// 必要选项存在检查Sd_NecessaryOptionsExistCheck(...);
}

11.2 会话ID管理

static void Sd_SaveRemoteSessionId(...) {sesIdCtrlPtr->rxMultiSesIdCnt = Sd_NtoHs(header.SessionID);sesIdCtrlPtr->rxMultiRebootFlag = header.RebootFlag;
}

11.3 重启检测

static boolean Sd_RemoteRebootDetecte(...) {if (((0u == lastRebootFlag) && (1u == header.RebootFlag)) ||((1u == header.RebootFlag) && (curSessionId <= lastSessionId)) {isReboot = TRUE;}
}

十二、配置管理机制

12.1 动态配置支持

static uint16 Sd_GetType1ConfigurationOptionLength(...) {// 支持主机名和能力记录if (NULL_PTR != sdInstancePtr->SdInstanceHostname) {cfgOptlen += 10u + strlen(...);}// 记录长度计算for (index = 0u; index < recordNum; index++) {cfgOptlen += 1u + strlen(key) + 1u + strlen(value);}
}

12.2 配置选项构建

static void Sd_BuildType1ConfigurationOption(...) {// 主机名选项keyLen = 8u; // "hostname"valueLen = strlen(sdInstancePtr->SdInstanceHostname);*optAddr = keyLen + valueLen + 1u;ILib_memcpy(optAddr+1, "hostname", 8);optAddr[9] = '=';ILib_memcpy(optAddr+10, hostname, valueLen);// 能力记录for (index = 0u; index < recordNum; index++) {keyLen = strlen(recordPtr->key);valueLen = (recordPtr->value) ? strlen(recordPtr->value) : 0u;*optAddr = keyLen + valueLen + 1u;ILib_memcpy(optAddr+1, recordPtr->key, keyLen);optAddr[keyLen+1] = '=';if (recordPtr->value) {ILib_memcpy(optAddr+keyLen+2, recordPtr->value, valueLen);}}
}

十三、版本特性实现

13.1 多播发送优化

支持连续发送Sd消息(V2.0.24)

static void Sd_IfSpecificRoutingGroupTransmit(void) {for (index = 0u; index < SD_EVENT_HANDLER_NUM; index++) {if (ehRTDataPtr->ifSpecificRoutingTransTcpFlag) {SoAd_IfSpecificRoutingGroupTransmit(ehRTDataPtr->routingGroupIdTcp, ehRTDataPtr->soConIdTcp);}if (ehRTDataPtr->ifSpecificRoutingTransUdpFlag) {SoAd_IfSpecificRoutingGroupTransmit(ehRTDataPtr->routingGroupIdUdp, ehRTDataPtr->soConIdUdp);}}
}

13.2 会话ID管理改进

static Sd_SessionIdCtrlType* Sd_AddRemoteAddrToSessionIdCtrlList(...) {sesIdCtrlPtr->txUniSesIdCnt = 0u;  // 单播计数初始化sesIdCtrlPtr->rxMultiSesIdCnt = 0u;  // 多播计数初始化
}

十四、编译配置管理

14.1 条件编译控制

#if SD_SERVER_SERVICE_NUM > 0
// 服务器相关代码
#endif#if SD_CLIENT_SERVICE_NUM > 0
// 客户端相关代码
#endif#if SD_CONSUMED_EVENTGROUP_NUM > 0
// 事件组相关代码
#endif

14.2 特性开关

#define SD_SUBSCRIBE_EVENTGROUP_RETRY_ENABLE STD_ON
#define SD_IPV6_ENABLE STD_OFF
#define SD_BSWM_USED STD_ON
#define SD_DEM_USED STD_ON

十五、运行时数据结构

15.1 服务器运行时(Sd_ServerServiceRTType)

typedef struct {uint32 initialWaitTimer;  // 初始等待定时器uint32 repetitionTimer;  // 重复发送定时器uint32 mainTimer;        // 主定时器Sd_SendQueueType* head; // 发送队列Sd_ServerServiceSetStateType setState; // 目标状态Sd_ServerServicePhaseType phase;     // 当前阶段Sd_TTLType ttl;                   // 生存时间uint8 repetitionCount;             // 重复计数
} Sd_ServerServiceRTType;

15.2 客户端运行时(Sd_ClientServiceRTType)

typedef struct {TcpIp_SockAddrType serverUdpAddr; // 服务器UDP地址TcpIp_SockAddrType offerEntryRemoteAddr; // 提供者地址PduIdType offerEntryRxPduId;      // PDU IDSd_TTLType ttl;                 // 生存时间Sd_SoConManageType tcpSoCon;   // TCP连接管理Sd_SoConManageType udpSoCon;   // UDP连接管理uint32 mainTimer;              // 主定时器uint8 repetitionCount;         // 重复计数boolean isSubscribed;          // 订阅状态boolean isAnsweredWithAck;     // 是否收到确认
} Sd_ClientServiceRTType;

十六、接口函数实现

16.1 服务状态设置(Sd_ServerServiceSetState)

Std_ReturnType Sd_ServerServiceSetState(...) {#if (STD_ON == SD_DEV_ERROR_DETECT)if (SD_UNINIT == Sd_Status) {SD_REPORT_ERROR(SD_SERVER_SERVICE_SET_STATE_ID, SD_E_NOT_INITIALIZED);return E_NOT_OK;}#endifSchM_Enter_Sd_ExclusiveArea();Sd_ServerRTData[handleId].setState = state;SchM_Exit_Sd_ExclusiveArea();return E_OK;
}

16.2 事件组状态设置(Sd_ConsumedEventGroupSetState)

Std_ReturnType Sd_ConsumedEventGroupSetState(...) {// 查找关联服务for (i = 0u; i < SD_CLIENT_SERVICE_NUM; i++) {if (SdConsumedEventGroupHandleId == handleId) {// 检查服务状态if (SD_CLIENT_SERVICE_RELEASED == cRtDataPtr->setState) {return E_NOT_OK;}// 更新状态consumedEgRTPtr->setState = ConsumedEventGroupState;if (SD_CONSUMED_EVENTGROUP_REQUESTED == ConsumedEventGroupState) {consumedEgRTPtr->isSendSubEvtAfterRequest = FALSE;}}}
}

十七、网络适配层交互

17.1 套接字管理

void Sd_ClientSaveSoConId(...) {// 设置唯一远程地址ret = SoAd_SetUniqueRemoteAddr(...);if (E_OK == ret) {// 打开套接字SoAd_OpenSoCon(...);soConPtr->isSoConOpened = TRUE;}
}

17.2 地址分配处理

void Sd_LocalIpAddrAssignmentChg(...) {// 更新实例IP地址状态Sd_InstanceRTData[idx].ipAddrState = State;// 通知地址变更Sd_SaveRemoteSessionId(...);
}

十八、消息打包发送

18.1 消息打包(Sd_PackageMessage)

static Std_ReturnType Sd_PackageMessage(...) {// 设置协议头Sd_SetHeader(...);// 填充条目长度tLengthField = Sd_HtoNl(entryTotalLen);ILib_memcpy(...);// 填充选项长度tLengthField = Sd_HtoNl(optionTotalLen);ILib_memcpy(...);// 复制条目和选项for (index = 0; index < sendQueCnt; index++) {ILib_memcpy(entryRunPtr, sendQuePtr->entryPtr, sizeof(Sd_Type1EntryType));entryRunPtr->Index1stOptions = optIdxCnt;optIdxCnt += sendQuePtr->optionNum;entryRunPtr = &entryRunPtr[16];}
}

18.2 发送调度(Sd_TransmitMessage)

static void Sd_TransmitMessage(void) {for (instanceIdx = 0u; instanceIdx < SD_INSTANCE_NUM; instanceIdx++) {// 优先发送单播uniSendCnt = Sd_FindoutUnicastMessage(...);if (uniSendCnt > 0u) {Sd_TransmitUnicastMessage(...);}// 然后发送多播multiSendCnt = Sd_FindoutMulticastMessage(...);if (multiSendCnt > 0u) {Sd_TransmitMulticastMessage(...);}}
}

十九、异常处理机制

19.1 消息格式检查(Sd_OptionFormatCheck)

static Std_ReturnType Sd_OptionEachItemFormatCheck(const uint8 optionArray[]) {switch (type) {case SD_CONFIGURATION_OPTION:// 配置选项始终有效ret = E_OK;break;case SD_IPV4_ENDPOINT_OPTION:// 检查长度和协议if ((0x09u == length) && ((SD_L4_PROTO_TCP == l4Proto) || (SD_L4_PROTO_UDP == l4Proto)) {ret = E_OK;}break;}
}

19.2 消息冲突检查(Sd_OptionsConflictCheck)

static Std_ReturnType Sd_OptionsConflictCheck(...) {uint16 ipv4EndpTcpNum = 0;uint16 ipv4EndpUdpNum = 0u;for (index = 0; index < optNumSum; index++) {if (SD_IPV4_ENDPOINT_OPTION == optType) {if (SD_L4_PROTO_TCP == ipv4Opt.L4Proto) {if (ipv4EndpTcpNum >= 1u) {ret = E_NOT_OK;  // TCP端点冲突}ipv4EndpTcpNum++;}}}
}

二十、高级特性实现

20.1 会话ID管理

static Sd_SessionIdCtrlType* Sd_FindRemoteAddrSessionIdCtrl(...) {while (sesIdCtrlPtr != NULL_PTR) {if (0 == ILib_memcmp(...)) {break;}sesIdCtrlPtr = sesIdCtrlPtr->next;}
}

20.2 重试机制(SD_SUBSCRIBE_EVENTGROUP_RETRY_ENABLE)

#if (STD_ON == SD_SUBSCRIBE_EVENTGROUP_RETRY_ENABLE)
void Sd_ClientServiceResetAllCEgSubsEntrySubsRetryCnt(...) {for (index = 0u; index < eventGroupNum; index++) {consumedEgRTPtr->subsRetryCnt = 0u;consumedEgRTPtr->subsRetryTimer = 0u;consumedEgRTPtr->subsRetryEnable = FALSE;}
}
#endif

20.3 路由控制

static void Sd_EnableUnicastForSubscribedClient(...) {while (ptr != NULL_PTR) {SoAd_EnableSpecificRouting(routingGroupId, ptr->soConId);ptr = ptr->next;}
}

二十一、典型应用场景

21.1 服务发现

void Sd_RxIndication(...) {// 接收消息处理if (Sd_NPtrtoHl(&sdMsg[SD_ENTRIES_ARRAY_LENGTH_INDEX]) + Sd_NPtrtoHl(&sdMsg[SD_ENTRIES_ARRAY_LENGTH_INDEX + entryArrayLen + 4u]) <= PduInfoPtr->SduLength) {// 添加到接收队列Sd_AppendToRxBuffTail(rxQueuePtr);}
}

21.2 事件组订阅

static void Sd_ClientServiceMainPhaseHandle(...) {// 订阅消息发送if (FALSE == consumedEgRTPtr->isAnsweredWithAck) {Sd_BuildSubscribeEventgroupEntry(...);}// 重试机制#if (STD_ON == SD_SUBSCRIBE_EVENTGROUP_RETRY_ENABLE)if (consumedEgTimerPtr->SdSubscribeEventgroupRetryMax > 0u) {consumedEgRTPtr->subsRetryTimer = ...;consumedEgRTPtr->subsRetryEnable = TRUE;}#endif
}

21.3 网络异常恢复(续)

TCP连接异常恢复
static void Sd_ClientServiceCloseSoCon(Sd_SoConManageType* soConPtr) {if (TRUE == soConPtr->isSoConOpened) {(void)SoAd_CloseSoCon(soConPtr->soConId, TRUE);soConPtr->isSoConOpened = FALSE;soConPtr->isOptRcved = FALSE;SoAd_ReleaseRemoteAddr(soConPtr->soConId);}
}

当检测到TCP连接状态变化为SOAD_SOCON_OFFLINE时,SD模块会主动关闭当前连接并释放资源。这种机制确保了在网络异常情况下,客户端能够及时清理无效的连接状态,避免系统资源浪费。

UDP连接异常恢复
static void Sd_ResetSoConToWildcard(...) {if (TRUE == resetFlag) {SoAd_ReleaseRemoteAddr(soConId);}
}

对于UDP连接,当检测到没有订阅者使用该连接时,模块会将连接重置为通配符模式。这种设计保证了在订阅关系变更后,系统能自动释放不再需要的资源。


21.4 消息重传机制

订阅事件组重试
#if (STD_ON == SD_SUBSCRIBE_EVENTGROUP_RETRY_ENABLE)
static void Sd_ClientServiceResetAllCEgSubsEntrySubsRetryCnt(...) {cEgRTPtr->subsRetryCnt = 0u;cEgRTPtr->subsRetryTimer = 0u;cEgRTPtr->subsRetryEnable = FALSE;
}
#endif

当订阅事件组请求未收到ACK确认时,模块会根据配置启动重试机制。通过subsRetryTimersubsRetryCnt字段跟踪重试次数,确保在达到最大重试次数后停止尝试。


21.5 安全检查机制

IP地址子网检查
static Std_ReturnType Sd_IsIpAddrInSameSubset(...) {// 子网掩码计算for (index = 0u; index < clrByte; index++) {netmaskArray[tAddrLen - index] = 0x00;}// 地址比较cmpResult = ILib_memcmp(addr1AndResult, addr2AndResult, addrLen);if (0 == cmpResult) {ret = E_OK;}
}

模块通过子网掩码对通信双方的IP地址进行校验,确保只有同一子网内的设备可以建立连接。这种机制有效防止了跨子网的非法访问。


21.6 版本兼容性处理

协议版本检查
void Sd_Init(...) {// 头部字段填充header.ProtocolVersion = 0x01u;header.InterfaceVersion = 0x01u;header.MessageType = 0x02u;header.ReturnCode = 0x00u;
}

初始化过程中,模块会设置标准的协议版本和接口版本,确保与其他节点的兼容性。版本不匹配的消息会被自动丢弃,防止协议不一致导致的问题。


21.7 内存管理优化

内存池初始化
SD_LOCAL_INLINE uint8 Sd_InitMemoryPool(uint32 memPoolSize, void* memPool) {return ILib_MemHeapInit(memPool, memPoolSize);
}

模块采用静态内存池管理机制,通过Sd_InitMemoryPool初始化内存池,避免动态内存分配带来的不确定性,提高系统可靠性。


22. 应用案例分析

22.1 车载娱乐系统服务发现

在车载娱乐系统中,多个ECU需要动态发现彼此提供的服务。例如,导航ECU需要发现音频处理ECU提供的音频播放服务:

// 导航ECU客户端配置
const Sd_ClientServiceType NavClientService = {.SdClientServiceId = 0x0100, // 导航服务ID.SdClientServiceInstanceId = 0x0001, // 实例ID.SdClientServiceMajorVersion = 0x01, // 主版本.SdClientServiceMinorVersion = 0x00000001, // 次版本.SdClientServiceTimerRef = &NavTimerConfig,.SdClientServiceTcpRef = &NavTcpConnection,.SdClientServiceUdpRef = &NavUdpConnection
};// 音频ECU服务配置
const Sd_ServerServiceType AudioServerService = {.SdServerServiceId = 0x0100, // 服务ID.SdServerServiceInstanceId = 0x0001, // 实例ID.SdServerServiceMajorVersion = 0x01, // 主版本.SdServerServiceMinorVersion = 0x00000001, // 次版本.SdServerServiceAutoAvailable = TRUE, // 自动可用.SdServerServiceTimerRef = &AudioTimerConfig,.SdServerServiceTcpRef = &AudioTcpConnection,.SdServerServiceUdpRef = &AudioUdpConnection
};

初始化后,导航ECU会周期性发送FindService请求,音频ECU响应OfferService消息,建立服务连接。

22.2 自动驾驶系统的事件组订阅

自动驾驶系统中,多个传感器节点需要订阅主控单元发布的事件组:

// 雷达事件组配置
const Sd_EventHandlerType RadarEventHandler = {.SdEventHandlerEventGroupId = 0x0200, // 事件组ID.SdEventHandlerTimerRef = &RadarTimerConfig,.SdEventHandlerTcp = &RadarTcpConfig,.SdEventHandlerUdp = &RadarUdpConfig
};// 主控单元处理订阅
static void Sd_RxSubscribeEventgroupHandle(...) {// 检查必要选项optionCheck = Sd_NecessaryOptionsExistCheck(...);// 构建ACK响应Sd_BuildSubscribeEventgroupAckEntry(...);// 管理订阅者TTLSd_SubscribeClientTTLManage(...);
}

主控单元通过TTL管理订阅者生命周期,确保失效订阅及时清理,维护系统稳定性。

22.3 网络拓扑变化处理

当车辆网络拓扑变化时,模块能自动适应:

void Sd_LocalIpAddrAssignmentChg(...) {for (idx = 0u; idx < SD_INSTANCE_NUM; idx++) {if (txPduSoConId == SoConId) {Sd_InstanceRTData[idx].ipAddrState = State;}}
}static void Sd_ServerServiceDownPhaseEnter(...) {// 重新初始化连接for (index = 0u; index < soConIdNum; index++) {(void)SoAd_OpenSoCon(soConIdList[index]);}
}

当IP地址重新分配时,模块会自动重新初始化相关连接,确保服务发现机制持续有效。


23. 模块优势与局限性

23.1 优势分析

  1. AUTOSAR标准兼容:完全遵循AUTOSAR R19-11规范,确保与其他AUTOSAR组件的互操作性。
  2. 高效内存管理:采用静态内存池,避免动态分配带来的不确定性。
  3. 多协议支持:同时支持IPv4和IPv6(通过编译开关)。
  4. 安全增强:通过子网检查防止跨网络访问。
  5. 灵活配置:允许通过配置文件调整定时参数、内存池大小等关键参数。

23.2 局限性探讨

  1. IPv6支持有限:当前实现中IPv6支持被禁用,限制了下一代网络的应用。
  2. 内存占用:预分配的运行时数据结构可能在低内存系统中造成资源浪费。
  3. 错误处理机制:虽然提供了DET和DEM接口,但具体错误恢复策略需依赖外部实现。
  4. 并发处理:发送队列采用链表结构,高并发场景下可能影响性能。

24. 未来优化方向

24.1 IPv6全面支持

// 当前配置
#define SD_IPV6_ENABLE STD_OFF// 未来优化
#define SD_IPV6_ENABLE STD_ON

启用IPv6支持需要完善IPv6相关选项处理函数,如Sd_SetIPv6EndpointOptionSd_SetIPv6MulticastOption

24.2 内存管理优化

// 当前内存池配置
#define SD_RX_MEMORY_POOL_SIZE 1024
#define SD_TX_MEMORY_POOL_SIZE 2048// 优化方向
typedef struct {uint8* pool;uint32 size;uint32 used;
} Sd_MemoryPoolType;SD_LOCAL_INLINE void* Sd_MallocEx(uint32 size, Sd_MemoryPoolType* memPool) {if (memPool->used + size <= memPool->size) {void* ptr = memPool->pool + memPool->used;memPool->used += size;return ptr;}return NULL_PTR;
}

引入更智能的内存管理策略,提高内存利用率。

24.3 错误恢复增强

// 当前错误处理
#if (SD_DEM_USED == STD_ON)
Dem_ReportErrorStatus(demEventPtr->EventId, DEM_EVENT_STATUS_FAILED);
#endif// 增强方向
typedef enum {SD_RECOVERY_NONE,SD_RECOVERY_RETRY,SD_RECOVERY_REINIT,SD_RECOVERY_FALLBACK
} Sd_RecoveryStrategyType;typedef struct {Sd_RecoveryStrategyType strategy;uint8 maxAttempts;uint32 retryInterval;
} Sd_ErrorRecoveryConfigType;

增加多样化的错误恢复策略,提升系统鲁棒性。


25. 总结

AUTOSAR SD模块实现了完整的服务发现和事件组订阅机制,其设计特点包括:

  1. 分层架构:严格区分头部、条目、选项等数据结构,提高代码可维护性。
  2. 状态机驱动:采用明确的状态机管理服务生命周期,确保逻辑清晰。
  3. 安全增强:通过子网检查和选项冲突检测防止非法访问。
  4. 资源管理:内存池和连接管理机制保障系统稳定性。
  5. 事件驱动:与BSWM模块集成,实现状态变更的通知机制。

模块在汽车以太网通信中发挥着基础性作用,其设计充分考虑了汽车电子系统的特殊需求。尽管存在IPv6支持不完整等局限,但通过合理的配置和优化,可以满足大多数车载场景的需求。随着车载网络的不断发展,该模块需要持续演进,特别是在内存管理、错误恢复和协议扩展方面,以适应更复杂的网络环境。


本文中的源代码实现来源于小满开源项目。

http://www.xdnf.cn/news/13699.html

相关文章:

  • 面试遇到的商城项目相关问题总结
  • 【Python基础】Python中字典知识点梳理
  • 预训练CNN网络的迁移学习(MATLAB例)
  • 在线机考|2025年华为暑期实习春招秋招编程题(最新)——第1题_物流运输
  • 【leetcode】104. 二叉树的最大深度
  • Spring上下文模块设计
  • 高防IP是怎么防御的?高防IP的防御步骤又有哪些?
  • SKE 与 SM2、SM3、SM4 的关系 ,SPDM协议的详细解析
  • 【Bitcoin基础】比特币的地址格式有哪些?如何应用?
  • 如何正确评估服务器CPU/内存/IO利用率 (性能过剩or瓶颈)
  • Spring涉及的设计模式以及实际使用场景(含代码)
  • 汽车电池智造关键一环!DeviceNet转Modbus RTU网关的实战突围
  • pod重启次数过多怎么排查
  • 数据结构 散列表 学习 2025年6月12日15:30:48
  • 旧物新生,绿色领航——旧物二手回收软件开启资源循环新篇章
  • 超维智联 质胜千里:晨控 RFID 驱动汽车后视镜智造跃迁
  • 离婚房产分割折价款计算的司法裁判策略
  • 13.15 LLaMA 3+LangChain重构语法学习:可视化语法树+智能纠错让效率翻倍!
  • VScode使用npm启动项目以及npm install ,npm start报错问题处理
  • ThreadLocal原理及内存泄漏分析
  • EVNIA 27M2N3500UK显示器荣膺TÜV莱茵圆偏光认证,树立健康显示新标杆
  • Web 架构之 Kubernetes 弹性伸缩策略设计
  • CHI协议验证中的异常及边界验证
  • 输电线防山火在线监测装置:科技赋能电网安全防线
  • 泛微OAe9-自定义资源看板
  • 纯血HarmonyOS ArKTS NETX 5 打造小游戏实践:大鱼吃小鱼(附源文件)
  • G1周打卡——GAN入门
  • 考研系列—408真题操作系统篇(2015-2019)
  • 煜邦智源SNEC全球首发智慧储能系统,携手德国莱茵TÜV加速全球化布局
  • Java 中使用 Redis 注解版缓存——补充