AUTOSAR图解==>AUTOSAR_AP_EXP_ARARustApplications

AUTOSAR自适应平台中的Rust应用程序

AUTOSAR AP_EXP_ARARustApplications解析与图解

目录

1. 介绍

本文档介绍了在Rust编程语言中编写AUTOSAR自适应应用程序的程序员接口的当前提案。这个API是在AUTOSAR Rust工作组内创建的。

本文档的目标读者是希望用Rust编程语言编写自适应应用程序的应用程序开发人员。假定读者对自适应AUTOSAR概念及其C++应用程序编程接口有一定的熟悉度。

1.1 动机

C++在汽车领域使用中的挑战,如内存管理复杂性、多线程复杂性、默认复制语义、缺少越界检测等,促使我们引入AUTOSAR自适应Rust绑定。引入Rust绑定的目的是利用Rust的优势来使用AUTOSAR自适应平台,并可能进行未来的结构性变更。

Rust是一种相对较新的编程语言,具有现代化的工具链。它方便、快速发展,且对C++开发人员来说易于理解。它在许多传统上在C++中难以管理的领域带来了改进。Rust还具有高级的编译时检查,可以防止代码中常见但非凡的错误类别。

1.2 Rust绑定优势

引入Rust旨在解决C++的以下挑战:

用例C++方法Rust方法
内存管理速度优化的手动内存管理编译时检查的形式化基于所有权的内存管理
多线程应用程序的数据保护通过文档关联关键部分和数据,通过运行时检测Send和Sync限制线程本地和并发访问,由编译器检查
数组类数据类型的越界检测默认不进行边界检查。检查边界是更冗长的变体始终在编译时或运行时检查,未检查的访问很冗长且需要仔细审查
对象语义对象默认被复制,指针之间可能存在别名对象默认被移动,跨模块防止读写干扰
语言设计重点速度和最大灵活性正确性与足够好的速度
对象初始化由静态分析器检查初始化编译器要求对象初始化
模块在C++20中引入模块是核心语言功能
宏绕过语法检查并具有非本地效应声明性和程序性类型的宏。支持内省和可变数量的参数
代码检查和审查各种代码检查器、依赖管理和构建系统、代码风格单一广泛接受的解决方案:Clippy、cargo、rustfmt
类型转换隐式转换由MISRA检查防止仅显式类型转换
无栈协程从C++20开始的co_await从2018年开始的async

注1:错误传播将自动转换错误类型。

1.3 绑定方法论

尽管有几种Rust绑定生成器可用,我们引入了手动实现的AUTOSAR自适应API的Rust绑定,以提供社区同意并审查的绑定,并避免语言之间自动数据类型转换的不一致性。随着Rust绑定生成器变得更加功能丰富和生产就绪,这种方法可能在未来发生变化。在我们的Rust绑定方法论中,我们希望利用自上而下(包设计驱动实现)和自下而上(接口实现导致可用的包结构)两种世界的最佳部分,以引入易于理解、快速适应新项目并最小化错误使用情况的Rust绑定。

在这里插入图片描述

1.3.1 分层架构

从一个简单的应用程序开始,暂时省略ARXML生成的代码,我们可以看到Rust应用程序支持需要多个层。Rust API适配器不能直接与AUTOSAR C++ API通信,因为Rust和C++对象之间没有共同的二进制互操作性。需要一个语言无关的二进制接口ABI。

定义这个接口的一种选择是使用C兼容的数据类型和调用约定,因为C语言的标准化二进制接口可以从C++和Rust两者访问。当前实现在Rust端定义了这个接口,并使用cbindgen生成供C++适配器使用的C(++)头文件。

请注意,这里并不存在用于此目的的C代码,它仅仅使用Rust和C++的C兼容子集进行互操作。

放大AUTOSAR特定部分,它由应用程序无关代码和ARXML生成的代理和骨架代码组成。中间列包含每个骨架或代理的三个单独文件,这些文件是从ARXML生成的:

  1. ara::com
  2. ara::com适配层
  3. ara::com Rust包装器

2. Rust异步编程架构

在AUTOSAR自适应平台中使用Rust编程时,异步编程是一个核心概念,它允许有效地处理I/O操作、通信和并发。以下是Rust异步编程架构的详细解析:

在这里插入图片描述

2.1 异步操作和执行器

Rust的异步编程模型基于非阻塞操作,允许程序在等待I/O或其他操作完成时继续执行其他任务。这种模型的核心是异步函数和执行器:

  1. 异步函数:使用async关键字标记的函数,它会创建一个表示将来某个时刻完成的计算的Future对象。

    • 异步函数的返回类型通常是impl Future<Output = T>
    • 异步函数可以使用.await语法等待其他Future完成
  2. 执行器:负责调度和执行异步任务的组件,它管理任务队列并确保任务在就绪时得到执行。

    • 执行器维护任务队列并轮询任务以检查它们是否可以取得进展
    • 常见的执行器包括tokio、async-std和futures库中的执行器
  3. 事件循环:执行器的核心组件,负责监控I/O事件并唤醒相应的任务。

    • 事件循环使用操作系统提供的非阻塞I/O原语(如epoll、kqueue或IOCP)
    • 当事件发生时,事件循环会唤醒等待该事件的任务

2.2 Future和任务

Rust的异步编程基于Future特性,它表示将来某个时刻可用的值:

  1. Future特性:表示异步计算的核心抽象,具有poll方法,该方法检查计算是否完成。

    pub trait Future {
        type Output;
        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
    }
    
  2. Pin:一种特殊的类型,确保Future不会在内存中移动,这对于包含自引用数据的Future是必需的。

    • Pin保证对象在内存中的位置不会改变
    • 这允许安全地创建自引用结构,这在异步代码中很常见
  3. 任务(Task):包装Future的执行单元,包含状态和唤醒器。

    • 任务包含Future对象、当前状态和唤醒器(Waker)
    • 唤醒器用于通知执行器任务已准备好进行进一步处理

2.3 I/O操作和同步原语

Rust异步编程提供了处理I/O和同步的原语:

  1. 异步I/O:非阻塞的读写操作,允许程序在等待I/O完成时执行其他任务。

    • 异步I/O操作返回Future而不是直接阻塞
    • 例如:async fn read(&mut self, buf: &mut [u8]) -> Result<usize>
  2. 流(Stream):表示一系列异步值,类似于同步迭代器。

    pub trait Stream {
        type Item;
        fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
    }
    
  3. 同步原语:异步版本的互斥锁、读写锁等,允许多个任务安全地共享数据。

    • Mutex<T>:异步互斥锁,保证对数据的独占访问
    • RwLock<T>:异步读写锁,允许多个读取者或单个写入者
    • 这些原语确保在等待锁时不会阻塞执行器

在AUTOSAR自适应平台中,这种异步架构使Rust应用程序能够高效地处理通信、定时器和I/O操作,同时保持响应性和资源效率。

3. ara::com绑定生成架构

AUTOSAR自适应平台中的通信是通过ara::com接口实现的,为了在Rust中使用这些接口,需要一套完整的绑定生成架构:

在这里插入图片描述

3.1 服务定义

ara::com绑定生成的起点是ARXML服务定义:

  1. ARXML文件:包含服务接口的完整定义,包括:

    • 服务接口定义:描述服务的名称、版本和命名空间
    • 类型定义:定义服务使用的数据类型,如结构体、枚举和类型别名
    • 方法定义:描述服务提供的方法,包括输入参数和返回类型
    • 事件定义:描述服务可以触发的事件
  2. 服务设计考虑:ARXML文件通常由系统设计人员创建,基于功能需求和系统架构。它们定义了服务的契约,所有通信必须遵循这个契约。

3.2 代码生成过程

从ARXML服务定义开始,代码生成过程涉及多个步骤:

  1. C++代码生成器:从ARXML生成C++代码,包括:

    • C++代理代码:客户端用于调用服务的代码
    • C++骨架代码:服务实现用于处理请求的代码
    • C++数据类型:用于在服务之间传输数据的类型
  2. Rust绑定生成器:从ARXML生成Rust代码,包括:

    • Rust代理代码:提供类型安全的异步API
    • Rust骨架代码:实现处理服务请求的异步处理程序
    • Rust数据类型:在Rust中表示服务数据类型的结构
  3. cbindgen:用于从Rust代码生成C/C++头文件的工具,这些头文件定义了Rust和C++代码之间的接口。

3.3 C++与Rust侧代码交互

生成的代码在C++和Rust之间通过以下组件进行交互:

  1. C++侧代码

    • 代理代码(C++):提供服务客户端API,处理序列化和异步调用
    • 骨架代码(C++):实现服务提供者逻辑,接收请求并调度处理程序
    • C++适配器:连接Rust和C++代码,处理内存管理和类型转换
  2. Rust侧代码

    • 代理代码(Rust):提供Rust异步API,返回Future对象
    • 骨架代码(Rust):实现服务处理逻辑,支持异步处理
    • Rust适配器:处理FFI边界,安全封装unsafe代码,管理所有权和生命周期
  3. 应用代码

    • C++应用:可以使用C++代理调用服务,或实现C++服务骨架
    • Rust应用:使用Rust代理异步调用服务,或实现异步服务

这种架构允许C++和Rust代码无缝互操作,同时利用两种语言的优势:C++的广泛使用和与现有AUTOSAR代码的兼容性,以及Rust的安全性、并发性和现代语言特性。

4. AUTOSAR-Rust通信场景

在AUTOSAR自适应平台中,服务之间的通信可以发生在不同的语言环境中。下图展示了四种可能的通信场景:

在这里插入图片描述

4.1 纯C++通信

这是最传统的场景,其中C++代理与C++骨架之间进行通信:

  1. 发送方:C++代理组件(如激光雷达应用代理)
  2. 接收方:C++骨架组件(如激光雷达应用骨架)
  3. 特点
    • 使用原生C++ ara::com API
    • 不需要跨语言桥接
    • 遵循标准AUTOSAR通信流程

4.2 C++到Rust通信

在这种场景中,C++客户端调用Rust服务:

  1. 发送方:C++代理组件(如摄像头应用代理)
  2. 接收方:Rust骨架组件(如摄像头应用骨架)
  3. 特点
    • C++客户端使用标准C++ ara::com API
    • Rust服务实现使用Rust ara::com骨架
    • 通过语言无关的二进制接口(ABI)进行通信
    • Rust服务能够利用Rust的安全特性和并发模型

4.3 Rust到C++通信

在这种场景中,Rust客户端调用C++服务:

  1. 发送方:Rust代理组件(如超声波应用代理)
  2. 接收方:C++骨架组件(如超声波应用骨架)
  3. 特点
    • Rust客户端使用Rust ara::com代理API
    • C++服务使用标准C++ ara::com骨架
    • Rust调用被转换为C++接口调用
    • Rust客户端能够使用异步编程模型

4.4 纯Rust通信

这是最现代化的场景,完全在Rust环境中进行通信:

  1. 发送方:Rust代理组件(如雷达应用代理)
  2. 接收方:Rust骨架组件(如雷达应用骨架)
  3. 特点
    • 完全使用Rust ara::com API
    • 充分利用Rust的所有优势:安全性、并发性、异步编程
    • 仍然与AUTOSAR通信机制兼容
    • 提供现代化的错误处理和类型安全

这四种通信场景展示了AUTOSAR自适应平台与Rust的灵活集成,允许渐进式采用Rust,同时保持与现有C++代码的互操作性。这种灵活性使团队能够在保持系统完整性的同时逐步引入Rust的优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KaiGer666

慧眼~施主!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值