2. 理解AUTOSAR分层架构在QNX上的映射

任务目标

在QNX Neutrino实时操作系统上部署AUTOSAR经典平台时,需要将AUTOSAR的三层软件架构(应用层、RTE、BSW)映射到QNX的进程/线程模型上。本案例通过一个最小可运行的示例,展示这种映射关系,并绘制对应的架构映射图。

AUTOSAR分层与QNX进程模型的映射关系

AUTOSAR层QNX映射方式说明
应用层(SWC)独立进程(Process)每个软件组件(SWC)运行在独立的QNX进程中,进程间通过QNX消息传递(Message Passing)通信,天然隔离故障。
RTE(运行时环境)进程间通信(IPC)封装层RTE的端口通信映射为QNX消息传递或共享内存。本案例用QNX消息传递实现RTE的Sender-Receiver通信语义。
BSW(基础软件)系统级服务进程/驱动BSW中的OS、COM、MCAL等模块映射为QNX系统服务(如资源管理器)、驱动进程或内核态驱动。本案例用一个独立的BSW服务进程模拟ECU状态管理。

最小可复现实现

以下代码在QNX Neutrino 7.x环境下编译运行,演示一个简化的AUTOSAR映射:一个应用进程(App_SWC)周期性地通过RTE层向另一个应用进程(Ctrl_SWC)发送车速信号,Ctrl_SWC收到后向BSW服务进程请求ECU状态并打印结果。

/* rte.h - RTE层API,封装QNX消息传递 */
#include <sys/neutrino.h>
#include <stdint.h>

#define MSG_TYPE_SPEED  1
#define MSG_TYPE_ECU_ST 2

typedef struct {
    uint16_t msg_type;
    int32_t  value;
} rte_msg_t;

/* 发送车速信号到Ctrl_SWC(阻塞式消息发送) */
static inline int RTE_SendSpeed(int coid, int32_t speed) {
    rte_msg_t msg = {MSG_TYPE_SPEED, speed};
    return MsgSend(coid, &msg, sizeof(msg), NULL, 0);
}

/* 请求ECU状态(先发请求再收响应) */
static inline int RTE_RequestEcuState(int coid, int32_t *state) {
    rte_msg_t msg = {MSG_TYPE_ECU_ST, 0};
    return MsgSend(coid, &msg, sizeof(msg), state, sizeof(*state));
}
/* app_swc.c - 应用层组件:周期发送车速信号 */
#include <stdio.h>
#include <process.h>
#include <sys/neutrino.h>
#include <unistd.h>
#include "rte.h"

int main(int argc, char **argv) {
    int coid = name_open("ctrl_swc", 0);
    if (coid == -1) { perror("name_open"); return 1; }

    int32_t speed = 0;
    for (int i = 0; i < 5; i++) {
        speed += 10;
        if (RTE_SendSpeed(coid, speed) == -1) {
            perror("RTE_SendSpeed");
            break;
        }
        printf("[App_SWC] Sent speed: %d km/h\n", speed);
        sleep(1);
    }
    name_close(coid);
    return 0;
}
/* ctrl_swc.c - 应用层组件:接收车速并请求ECU状态 */
#include <stdio.h>
#include <process.h>
#include <sys/neutrino.h>
#include <stdint.h>
#include "rte.h"

int main(void) {
    name_attach_t *attach = name_attach(NULL, "ctrl_swc", 0);
    if (!attach) { perror("name_attach"); return 1; }

    int bsw_coid = name_open("bsw_svc", 0);
    if (bsw_coid == -1) { perror("name_open bsw"); return 1; }

    rte_msg_t msg;
    for (;;) {
        int rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL);
        if (rcvid == -1) { perror("MsgReceive"); break; }

        if (msg.msg_type == MSG_TYPE_SPEED) {
            int32_t ecu_state = 0;
            if (RTE_RequestEcuState(bsw_coid, &ecu_state) == -1) {
                perror("RTE_RequestEcuState");
            } else {
                printf("[Ctrl_SWC] Got speed=%d, ECU state=%d\n",
                       msg.value, ecu_state);
            }
        }
        MsgReply(rcvid, EOK, NULL, 0);
    }
    name_close(bsw_coid);
    name_detach(attach);
    return 0;
}
/* bsw_svc.c - BSW服务进程:提供ECU状态查询 */
#include <stdio.h>
#include <process.h>
#include <sys/neutrino.h>
#include <stdint.h>
#include "rte.h"

int main(void) {
    name_attach_t *attach = name_attach(NULL, "bsw_svc", 0);
    if (!attach) { perror("name_attach"); return 1; }

    rte_msg_t msg;
    for (;;) {
        int rcvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL);
        if (rcvid == -1) { perror("MsgReceive"); break; }

        if (msg.msg_type == MSG_TYPE_ECU_ST) {
            int32_t state = 0x01;  /* 模拟ECU正常状态 */
            MsgReply(rcvid, EOK, &state, sizeof(state));
        } else {
            MsgReply(rcvid, EOK, NULL, 0);
        }
    }
    name_detach(attach);
    return 0;
}

编译与运行

# 编译三个进程
qcc -o app_swc app_swc.c
qcc -o ctrl_swc ctrl_swc.c
qcc -o bsw_svc bsw_svc.c

# 运行(需在QNX目标机上,或使用qemu模拟)
./bsw_svc &
./ctrl_swc &
./app_swc

验证方法

运行后,app_swc每秒钟发送一次递增的车速值,ctrl_swc收到后向bsw_svc查询ECU状态并打印。预期输出如下(顺序可能因调度略有不同):

[App_SWC] Sent speed: 10 km/h
[Ctrl_SWC] Got speed=10, ECU state=1
[App_SWC] Sent speed: 20 km/h
[Ctrl_SWC] Got speed=20, ECU state=1
[App_SWC] Sent speed: 30 km/h
[Ctrl_SWC] Got speed=30, ECU state=1
[App_SWC] Sent speed: 40 km/h
[Ctrl_SWC] Got speed=40, ECU state=1
[App_SWC] Sent speed: 50 km/h
[Ctrl_SWC] Got speed=50, ECU state=1

通过条件:Ctrl_SWC打印的车速值与App_SWC发送值一致,且ECU state恒为1。若在ctrl_swc运行时按Ctrl+C终止bsw_svc,则ctrl_swc应打印错误信息,验证进程间通信的故障隔离特性。

架构映射图

AUTOSAR 应用层 RTE(运行时环境) BSW(基础软件层) App_SWC 进程 周期发送车速信号 Ctrl_SWC 进程 接收车速+查询ECU状态 RTE 映射:QNX 消息传递(MsgSend / MsgReceive) 端口通信 → 进程间IPC通道 BSW 服务进程 ECU状态管理(模拟) 车速信号 (RTE_SendSpeed) ECU状态请求 状态响应 独立进程,故障隔离 IPC通道由name_open/name_attach建立 系统级服务,可被多个SWC共享

图中展示了三个独立QNX进程之间的消息流向:App_SWC通过RTE封装的消息发送接口将车速信号传递给Ctrl_SWC;Ctrl_SWC再通过RTE向BSW服务进程发起ECU状态请求并接收响应。这种映射方式保留了AUTOSAR的分层解耦特性,同时利用QNX的进程隔离增强了系统可靠性——任一应用进程崩溃不会影响其他进程或BSW服务。