目录

AUTOSAR_SWS_OperatingSystemInterface_R2011

AUTOSAR_SWS_OperatingSystemInterface


7 功能规范

7.1 功能集群生命周期

7.1.1 操作系统概述

嵌入式汽车ECU中的实时操作系统为软件应用的动态行为提供了基础。它管理进程和事件的调度、不同进程之间的数据交换与同步,并提供监控和错误处理的功能。本章描述了面向操作系统的需求。应用,特别是自适应应用,可能没有系统权限来直接完全使用或配置这些方面。

7.1.2 进程处理

[SWS_OSI_01040] 启动执行管理作为初始进程。 [操作系统应允许将执行管理作为AUTOSAR自适应平台的初始进程启动。]

[SWS_OSI_01006] 多线程支持。 [操作系统应允许运行多个执行上下文(线程),使得进程能够执行多个代码流。]

在多核平台上,[SWS_OSI_01006] 所允许多个线程可能在不同的核上并发执行。所有线程都属于某个进程,因此同一进程中的多个线程可能同时在多个核上并发执行。此外,执行管理需要能够将特定进程绑定到某个核,作为资源管理的一部分 [SWS_EM_02104]。

[SWS_OSI_01012] 核心亲和性规范。 [操作系统应提供将进程绑定到CPU核心的机制。]

通常,一个进程至少提供以下内容:

  • 一个 main() 函数,作为进程第一个执行线程的入口点。
  • 一个本地内存上下文(地址空间),提供本地、非共享的内存,至少包括进程的代码、数据和堆。
  • 一定程度的内存保护,使得底层操作系统能够检测到不正确或无效的内存访问。
  • 允许访问操作系统所管理资源的操作系统描述符。

[SWS_OSI_01008] 多进程支持。 [操作系统应支持多进程。]

[SWS_OSI_01009] 多进程隔离。 [操作系统应将每个进程相互隔离,使得不正确或无效的内存访问能够被操作系统检测到。]

[SWS_OSI_01014] 多进程创建能力限制。 [操作系统应允许将进程配置为禁止创建其他进程。]

[SWS_OSI_01010] 虚拟内存。 [操作系统应在每个进程专用的地址空间中执行该进程。]

每个进程都有自己的逻辑地址空间,代码和数据位于其中。由于进程的地址空间是虚拟化的,该地址可能对应也可能不对应其底层的物理地址空间。特别是,在不同逻辑地址空间中运行的同一可执行文件的多个实例,可以共享其代码和只读数据的物理地址(因为是只读的),以节省一些物理内存。而可写数据则需要分开,因此它们被映射到不同的物理地址。

共享对象(有时也称为DLL)通常包含可同时供多个进程使用的代码和数据。当多个进程使用一个共享对象时,该共享对象的代码和只读数据通常映射到每个进程中,但在系统内存中仅存在一份,而共享数据可能会被立即复制或在需要时复制(写时复制,CoW)。

共享对象主要有两种使用方式:

  • 隐式加载:在构建时,可执行文件可以与一个共享对象链接;之后,在加载时,操作系统及其加载框架支持将该共享对象的代码和数据映射到应用进程中使用。这主要用于节省空间和方便部署共享代码的修复,但有时也出于许可原因。进程本身不需要任何特定能力或知道该共享库的存在即可使用它。
  • 显式加载:在运行时,进程请求操作系统及其加载框架打开并加载目标上的共享对象,并让其解析符号名称并加载其代码和数据。这通常用于插件机制,其中所有插件都暴露相同的共享符号。可执行文件本身在链接时不知道这些插件,并且通常使用 dlopen() / dlsym() / dlclose() 来启用插件式加载的共享对象。

[SWS_OSI_01013] 隐式共享对象支持。 [操作系统应允许对可执行文件使用隐式加载共享对象。]

注意,出于安全、防护或其他原因,可执行文件可以完全静态链接,因此不使用共享对象的能力。

7.1.3 调度策略

操作系统调度器旨在保持所有系统资源忙碌,允许多个软件控制流以有效的方式共享CPU核心。调度机制的主要目标可能包括以下一项或多项:

  • 通过每时间单位完成的工作量最大化吞吐量。
  • 通过最小化作业激活与实际开始数据处理之间的时间来最大化响应性。
  • 通过确保根据每个作业的优先级和工作量分配适当的CPU时间来最大化公平性。
  • 根据某些策略依赖的作业执行资格(例如优先级、截止时间、延迟等)保证作业按时间线有序激活。

在现实生活中,这些目标常常相互冲突,因此调度机制的实现始终是一种折衷。

[SWS_OSI_01003] 默认调度策略。 [AUTOSAR自适应平台操作系统应支持IEEE1003.1 POSIX标准中定义的以下调度策略:SCHED_OTHER、SCHED_FIFO、SCHED_RR。]

为了克服上述冲突并实现不同平台之间的可移植性,AUTOSAR自适应平台操作系统提供以下调度策略,分为两类:

  • 公平调度策略 SCHED_OTHER

  • 实时调度策略 SCHED_FIFO SCHED_RR

由于上述默认调度策略可能无法保证所有实时场景的正确执行,自适应应用供应商可以提供额外的调度策略来满足任何执行需求。例如,可以引入额外的非POSIX调度策略,如SCHED_DEADLINE(最早截止时间优先算法)来满足硬实时要求。

7.1.4 时间触发执行

POSIX PSE51提供了一种使用定时器API(例如 timer_settime())配合POSIX信号进行基于时间的周期性处理的方法。然而,信号有时不推荐用于安全关键型应用,因为它们会中断执行流。

使用C++时,可以使用 std::future::wait_until() 来实现周期性处理。TimeSync规范也可以与 std::future 一起使用以提供事件生成。然而,这两种API仅允许单次、相对时间的闹钟,而高效、低开销的实现需要周期性闹钟和/或绝对闹钟。

因此,这些API将来可能会被扩展。

7.1.5 设备支持

操作系统接口应按照POSIX PSE51中的定义支持设备访问。

7.1.6 资源控制

虽然期望每个应用都有正确行为,但必须遏制有意或无意的错误行为以保证系统稳定性。同时,必须允许一定程度的动态行为。从功能角度来看,应用可以被组合成组,使得它们可以遵循相似的使用模式,共享内存、CPU时间以及一般资源。

[SWS_OSI_02000] 资源组最低要求。 [操作系统应支持在系统中配置至少8个进程组。]

根据操作系统的不同,可用的资源组数量可能有所不同。此外,当使用操作系统级虚拟化容器时,某些操作系统可能会进一步限制可用的资源组数量,极端情况下只有1个可用的资源组。

[SWS_OSI_02001] 内存资源组。 [操作系统应支持一种机制,用于定义进程组,这些进程组可以从配置定义的限制中动态分配内存。]

考虑限制的内存包括:

  • 可执行文件的代码和只读数据
  • 可执行文件的可修改数据
  • 进程每个线程的线程栈所使用的内存
  • 操作系统用于保存分配给进程的内核资源(例如线程控制块、信号量、MMU的页表条目等)的系统内存
  • 同一组进程之间的共享内存
  • 同一组进程之间隐式加载的共享对象

由于不同操作系统的内存记账方式可能不同,某些元素可能被视为在或不在进程组的内存使用限制之内,具体实现方式由具体实现决定:

  • 不同组进程之间的共享内存
  • 内存映射文件
  • 不同组进程之间隐式加载的共享对象

[SWS_OSI_02002] CPU资源组。 [操作系统应支持一种机制,用于定义进程组,这些进程组可以在定义的时间段内使用最大配置的CPU时间量。]

由于调度方式因操作系统而异,具体的调度算法以及限制CPU使用的方法在此不进行描述。

有效的组调度方案示例包括(但不限于):

  • 在固定时间范围内以类似于ARINC 653标准定义的方式周期性启用进程。进程使用分配给该组的时间配额中的时间。如果没有剩余时间,则过期组中的任何进程的线程都不能被调度。每个周期,配额会被补充,以允许使用更多时间,并使得相应的线程再次被调度。
  • 进程累积时间使用。在每个周期或每次上下文切换时,计算过去一定周期数内累积的时间使用。使用时间超过阈值的每组进程中的进程被禁用,而使用时间低于阈值的每组进程中的进程被启用。

值得注意的是,在某些操作系统上,空闲时间(根据定义,没有被任何进程组请求使用)可以分配给任何进程,包括那些被认为使用时间超过定义限制的组中的进程。这是一种值得的优化,但目前规范中未将其作为要求。

7.2 启动

操作系统的启动步骤必须以特定于实现的方式执行。这些步骤包括启动任何操作系统相关中间件,包括设备驱动程序和处理底层中间件的服务,以及启动执行管理。

需要重点说明的是,预期执行管理将在系统启动早期启动,理想情况下作为第一个进程,以便能够启动所有所需的进程。然而,根据操作系统的不同,其他系统服务和支撑中间件可能在执行管理之前或与之并行启动。例如,如果操作系统有一个不属于其内核的文件系统服务,则该服务可能在此之前启动。

7.3 关闭

类似地,操作系统的关闭步骤是特定于实现的。它们可能包括刷新某些中间件缓冲区、关闭某些外设,并根据系统配置可选地关闭整个系统。