AUTOSAR_EXP_ARAComAPI的5章笔记(6)

返回目录

5.3.5.5 Event-Driven vs Polling-Based access

ara::com实现完全支持事件驱动轮询的方式来访问新数据。

对于轮询方式,典型的用例是,一个应用程序被周期性地触发在特定的截止时间前进行一些处理。这是调节器/控制算法的典型模式 —— 循环激活由一个实时定时器驱动,以确保最小的抖动。在这样的设置中,在每个激活周期中调用*GetNewSamples(),然后将那些更新的缓存数据用作当前处理迭代的输入。此时,应用程序在调度处理算法时获取最新的数据进行处理就完全足够了。如果ara::com实现在任何有新数据可用的时通知你的应用程序,那将适得其反:这只会意味着对你的应用程序进程进行不必要的上下文切换,因为在你收到通知的时候,你可能并不想处理那些新数据,因为还没到处理它的时候。

然而,也有其他用例。如果你的应用程序没有这样一种周期性的、由截止时间驱动的方法,而是应当在某些事件发生时简单地做出反应,那么设置周期性调用*GetNewSamples()来轮询新事件就有点不合适并且效率低下。在这种情况下,你明确希望ara::com实现通知应用程序,从而对应用程序进程进行异步上下文切换。我们通过以下 API 机制来支持这种方式:

ara::core::Result<void> SetReceiveHandler(ara::com::EventReceiveHandler handler);

这个 API允许你注册一个用户定义的回调函数,当自上次调用 GetNewSamples()以来有新的事件数据可用时,通信管理必须调用这个回调函数。注册的回调函数不需要是可重入的,因为ara::com实现必须序列化注册的回调函数,明确允许从注册的回调函数内部调用GetNewSamples()!

请注意,用户可以随时在事件驱动轮询方法之间切换,因为他也可以使用事件包装类提供的UnsetReceiveHandler()方法撤回用户特定的 “接收处理程序”。

以下简短的代码片段是一个关于在服务消费者如何使用事件的简单示例。在这个示例中,在main函数中创建了一个RadarService类型的Proxy实例,并注册了一个接收处理程序,每当接收到新的BrakeEvent事件时,ara::com实现就会调用这个处理程序。这意味着我们使用了“事件驱动” 方法。

在我们的示例中,我们在接收处理程序中用新接收到的事件更新我们的本地缓存,从而过滤掉所有不满足特定属性的BrakeEvent事件,之后,我们调用一个处理函数,该函数处理我们决定保留的Sample。

 #include "RadarServiceProxy.hpp"
 #include <memory>
 #include <deque>

 using namespace com::mycompany::division::radarservice;
 using namespace ara::com;

 /**
 * our radar proxy - initially the unique ptr is invalid.
 */
 std::unique_ptr<proxy::RadarServiceProxy> myRadarProxy;

 /**
 * a storage for BrakeEvent samples in fifo style
 */
 std::deque<SamplePtr<const proxy::events::BrakeEvent::SampleType>> stNActiveSamples;

 /**
 * \brief application function, which processes current set of BrakeEvent
 * samples.
 * \param samples
 */
 void processLastBrakeEvents(
 std::deque<SamplePtr<const proxy::events::BrakeEvent::SampleType>>&mples) 
 {
    // do whatever with those BrakeEvent samples ...
 }

 /**
 * \brief event reception handler for BrakeEvent events, which we register
 get informed about new events.
 */
 void handleBrakeEventReception() 
 {
     /**
     * we get newly arrived BrakeEvent events into our process space.
     * For each sample we get passed in, we check for a certain property
     * "active" and if it fulfills the check, we move it into our Last10-
    orage.
     * So this few lines basically implement filtering and a LastN policy.
     */
     myRadarProxy->BrakeEvent.GetNewSamples(
     [](SamplePtr<proxy::events::BrakeEvent::SampleType> samplePtr) 
     {
         if(samplePtr->active) 
         {
            lastNActiveSamples.push_back(std::move(samplePtr));
            if (lastNActiveSamples.size() > 10)
                lastNActiveSamples.pop_front();
         }
     });

     // ... now process those samples ...
     processLastBrakeEvents(lastNActiveSamples);
 }

 int main(int argc, char** argv) 
 {
    /* Instance Specifier from model */
    ara::core::InstanceSpecifier instspec {...}

    auto handles = proxy::RadarServiceProxy::FindService(instspec);

    if (!handles.empty()) 
    {
        /* we have at least one valid handle - we are not very particular
        * here and take the first one to create our proxy */
        myRadarProxy = std::make_unique<proxy::RadarServiceProxy>(handles[0]);

       /* we are interested in receiving the event "BrakeEvent" - so we
       * subscribe for it. We want to access up to 10 events, since our
       * sample algo averages over at most 10.*/
       myRadarProxy->BrakeEvent.Subscribe(10);

       /* whenever new BrakeEvent events come in, we want be called, so we
       * register a callback for it!
       * Note: If the entity we would subscribe to, would be a field
       * instead of an event, it would be crucial, to register our
       * reception handler BEFORE subscribing, to avoid race conditions.
       * After a field subscription, you would get instantly so called
       * "initial events" and to be sure not to miss them, you should care
       * for that your reception handler is registered before.*/
        myRadarProxy->BrakeEvent.SetReceiveHandler( handleBrakeEventReception);
    }

 // ... wait for application shutdown trigger by application exec mgmt.
 }

5.3.5.6 Buffering Strategies

以下图形描绘了一个简单的部署情况,其中有一个服务提供一个事件,两个不同的本地服务消费者(SWC)通过它们各自的Proxy的事件包装类订阅了这个事件。正如在图中看到的,两个Proxy都有一个本地事件缓存,可以通过GetNewSamples()填充的缓存。这幅图还描绘了服务实现将其事件数据发送到一个通信管理缓冲区,这个缓冲区显然在服务实现的进程空间之外 —— 图中假设这个缓冲区由内核拥有,或者为通信的Proxy和Skeleton之间的共享内存,或者由一个单独的特定于绑定实现的 “守护” 进程拥有。

3282cf9dd72a46418742d4d96f2630ca.png

图中假设如下:应用程序被实现为具有独立 / 受保护的内存 / 地址空间的进程。

服务实现(通过Skeleton)发送出的事件数据不能在服务 / 骨架进程的私有地址空间内缓冲:如果是这样的话,代理对事件数据的访问通常会导致切换到服务应用程序进程的上下文。我们希望在服务端通过方法调用处理模式(见 5.4.5 小节)对事件访问完全控制,不应该由服务消费者的通信行为触发。现在让我们大致看一下 “发送事件” 的目标缓冲区可能位于的三个不同位置:

  1. 内核空间:数据被发送到一个不在应用程序进程的内存区域。当绑定实现使用诸如管道套接字这样的进程间通信原语时,通常就是这种情况,写入这样一个原语的数据最终会在内核缓冲区空间中。
  2. 共享内存:数据被发送到一个内存区域,这个区域也可以直接被接收者 / 代理读取。不同方之间的写入 / 读取是专门同步的(使用内存屏障显式互斥锁进行轻量级同步)。
  3. 进程间通信守护进程空间:数据被发送到一个明确的非应用程序进程,这个进程充当进程间通信 / 绑定实现的一种守护进程。请注意,从技术上讲,这种方法可能建立在一个进程间通信原语之上,比如通过内核空间或共享内存进行通信,以便将数据从服务进程传输到守护进程。

这些方法中的每一种在缓冲区空间的灵活性 / 大小、访问速度 / 开销效率以及防止恶意访问 / 写入缓冲区的保护方面可能都有不同的优缺点。因此,在一个汽车开放平台(AP)产品及其使用中考虑不同的约束可能会导致不同的解决方案。

在这个例子中需要强调的是,鼓励 AP 产品供应商使用基于引用的方法来访问事件数据:事件包装类的ara::com API 有意地通过SamplePtr来建模访问,这些指针被传递给回调函数,而不是值!在那些相当典型的 1:N 事件通信场景中,允许在 “本地事件缓存” 中不是事件数据值本身,而是指向包含在中央通信管理缓冲区中的数据的指针 / 引用。然后,通过GetNewSamples()更新本地缓存可以实现为不是值的复制,而是引用的更新。

说实话:这显然是关于缓冲区使用优化可能性的一个粗略图景!正如这里所暗示的(7.1 节),传输到应用程序进程的数据通常必须在应用程序访问之前进行反序列化。由于反序列化必须特定于服务消费者的应用程序的对齐方式,因此,已经反序列化的数据在中央共享可能很棘手。但至少你明白了这一点,即:服务消费者的事件数据访问的API设计为消费者之间的事件数据共享提供了空间。

♦️♦️总结♦️♦️

1. Event - Driven vs Polling - Based access

1.1 轮询方式(Polling - Based access)

  • 典型用例:应用程序周期性被触发,在特定截止时间前处理,常见于调节器 / 控制算法,循环激活由实时定时器驱动以确保最小抖动。在每个激活周期调用*GetNewSamples(),用更新的缓存数据作为当前处理迭代输入,这种情况下,应用程序按调度获取最新数据处理即可,若有新数据就通知应用程序则可能造成不必要的上下文切换。

1.2 事件驱动方式(Event - Driven access)

  • 适用场景:当应用程序不是周期性、截止时间驱动,而是需在某些事件发生时简单做出反应,周期性调用*GetNewSamples()轮询新事件就不合适且效率低下,此时希望ara::com实现通知应用程序进行异步上下文切换。
  • 实现机制
    • 通过ara::core::Result<void> SetReceiveHandler(ara::com::EventReceiveHandler handler) API 注册用户定义的回调函数,当有新事件数据可用时通信管理调用该回调函数,注册的回调函数无需可重入,因为ara::com实现会序列化注册的回调函数,且允许从注册的回调函数内部调用GetNewSamples()
    • 用户可通过事件包装类提供的UnsetReceiveHandler()方法在事件驱动和轮询方法之间切换。
  • 示例代码
    • 创建RadarService类型的Proxy实例,并注册接收处理程序,当接收到新的BrakeEvent事件时ara::com实现调用该处理程序,在接收处理程序中更新本地缓存、过滤不满足特定属性的BrakeEvent事件并调用处理函数处理决定保留的Sample

2. Buffering Strategies

2.1 部署情况

  • 一个服务提供一个事件,两个本地服务消费者(SWC)通过各自Proxy的事件包装类订阅该事件,Proxy有本地事件缓存(通过GetNewSamples()填充),服务实现将事件数据发送到通信管理缓冲区,该缓冲区可能在以下位置:
    • 内核空间:数据发送到不在应用程序进程内存区域,使用进程间通信原语(如管道或套接字)时常见,数据最终在内核缓冲区空间。
    • 共享内存:数据发送到接收者 / 代理可直接读取的内存区域,不同方的写入 / 读取通过内存屏障或显式互斥锁进行轻量级同步。
    • 进程间通信守护进程空间:数据发送到明确的非应用程序进程(充当进程间通信 / 绑定实现的守护进程),从技术上讲可基于进程间通信原语(如通过内核空间或共享内存)将数据从服务进程传输到守护进程。

2.2 设计考虑

  • 鼓励汽车开放平台(AP)产品供应商使用基于引用的方法访问事件数据,事件包装类的ara::com API 通过SamplePtr建模访问(传递指针给回调函数而非值),在典型的 1:N 事件通信场景中,本地事件缓存中是指向中央通信管理缓冲区数据的指针 / 引用,GetNewSamples()更新本地缓存可实现为引用更新。虽然传输到应用程序进程的数据在访问前通常需反序列化且共享已反序列化的数据可能棘手,但 API 设计为消费者之间的事件数据共享提供了空间。

 

 

### 回答1: autosar_exp_vfb.pdf是一个与AUTOSARAutomotive Open System Architecture)相关的文件。该文件中的“exp”代表“实验”(experiment),“vfb”代表“虚拟功能总成”(virtual functional bus)。 AUTOSAR是一种开放的、标准化的汽车电子系统架构,旨在提供一种通用的软件架构和平台,使汽车制造商和供应商能够更轻松地开发可重用和可互换的汽车电子控制单元(ECU)。AUTOSAR定义了一组标准、协议和工具链,用于汽车电子系统中的软件和硬件组件之间的通信与互操作。 在autosar_exp_vfb.pdf文件中,主要介绍了AUTOSAR架构中的虚拟功能总成(VFB)的实验研究内容。虚拟功能总成是AUTOSAR架构中的重要概念之一,它是一种通过软件模型和封装技术来实现的虚拟函数,用于实现不同的汽车功能。通过VFB,不同的软件模块可以以相对独立的方式进行开发和测试,并在已经定义好的接口上进行互操作。 autosar_exp_vfb.pdf文件可能包括以下内容: 1. 虚拟功能总成的设计原理和方法:介绍了VFB的设计原则和实现方法,包括软件模型的构建、接口的定义、封装技术的应用等。 2. VFB与AUTOSAR架构的关系:解释了VFB在AUTOSAR架构中的位置和作用,以及VFB与其他AUTOSAR模块(如ECU软件组件等)之间的协作关系。 3. VFB的实验研究案例:给出了一些使用VFB实现特定汽车功能的实验案例,例如车身控制、驾驶辅助系统、车载娱乐等。 4. VFB的优势和挑战:分析了使用VFB进行软件开发的优势和挑战,如适应不同需求、提高开发效率、确保系统可靠性等。 总而言之,autosar_exp_vfb.pdf文件提供了关于AUTOSAR架构中虚拟功能总成的实验研究内容,介绍了其设计原理、与AUTOSAR架构的关系、实验案例以及优势和挑战。 ### 回答2: autosar_exp_vfb.pdf 是一个关于AUTOSARAUTomotive Open System ARchitecture)的实验报告文件。 AUTOSAR是一个汽车领域的开放系统架构标准,旨在促进汽车电子控制单元(ECU)软件的开发、集成和共享。该标准由一些汽车制造商、电子供应商和软件供应商共同组成的联盟开发,旨在提高汽车电子系统的可靠性、可扩展性和安全性。 autosar_exp_vfb.pdf 这个实验报告文件探讨了AUTOSAR架构中的虚拟功能总线(VFB)。虚拟功能总线是AUTOSAR的一个重要概念,用于在ECU之间进行通信和数据交换。 实验报告详细介绍了VFB的原理和实现方法,包括通信协议、消息传递方式和数据处理过程。它还讨论了VFB的优点和应用场景,并提供了一些实际案例和实验结果。 通过阅读autosar_exp_vfb.pdf,读者可以了解到VFB在AUTOSAR架构中的重要性和作用,以及如何使用VFB来实现ECU之间的通信和数据交换。这对汽车电子系统的开发人员和工程师来说是非常有价值的信息,可以帮助他们更好地理解和应用AUTOSAR标准。同时,这个实验报告也为研究AUTOSAR和汽车电子系统的学者和研究人员提供了一个有用的参考和指导。 ### 回答3: autosar_exp_vfb.pdf是一个自动驾驶相关的文件。该文件是Autosar Exp软件的一部分,主要涵盖了Virtual Function Bus(VFB)的概念和应用。 Virtual Function Bus是一个在自动驾驶系统中使用的通信框架,旨在实现模块化开发和集成。它允许系统中的不同功能模块以一种标准化的方式进行通信和互操作。 autosar_exp_vfb.pdf文件提供了关于VFB的详细说明和使用指南。在这个文件中,我们可以找到关于VFB的架构、功能和特性的详细描述。它还介绍了VFB的设计原则和使用方法,以及与其他Autosar软件模块的集成方式。 此外,autosar_exp_vfb.pdf文件还提供了一些示例应用和用例,以帮助开发人员理解和应用VFB。这些示例涵盖了VFB在自动驾驶系统中的实际应用,包括传感器数据的处理、决策制定和控制执行等方面。 总而言之,autosar_exp_vfb.pdf是一个重要的文件,它为开发人员提供了关于Virtual Function Bus的全面理解,帮助他们在自动驾驶系统中有效地设计和集成功能模块。这个文件对于开发自动驾驶系统的工程师和研究人员来说是一个有价值的参考资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

青草地溪水旁

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值