嵌入式系统Linux实时化(二)Xenomai技术框架分析

server/2025/1/12 7:27:05/

Xenomai 是 Linux 内核的一个实时开发框架。它希望通过无缝地集成到Linux 环境中来给用户空间应用程序提供全面的、与接口无关的硬实时性能。Xenomai 项目始于2001年8月,作为一个自由软件项目,完全遵守GNU/Linux自由软件协议。2003 年它和RTAI项目合并推出了RTAI/fusion。RTAI/fusion是Linux平台上的具有工业生产级别的实时自由软件开发平台,它基于Xenomai的抽象实时操作系统内核。2005年的时候RTAI/fusion项目又从RTAI中独立出来作为 Xenomai 项目。

与 RTLinux 类似,Xenomai 也是一种采用双内核机制的 Linux 内核的强实时扩展。在双内核技术下,存在一个支持强实时的微内核,它与Linux内核共同运行于硬件平台上,实时内核的优先级高于 Linux 内核,它负责处理系统的实时任务,而Linux则负责处理非实时任务,只有当实时内核不再有实时任务需要处理的时候,Linux 内核才能得到运行的机会。

Xenomai最新的技术架构可以访问其网站www.xenomai.org

双核(如RTLinux,RTAI,Xenomai)实时方案。运作一个real-time核心,然后将修改过的GNU / Linux核心程序码视为该实时核心的空闲任务。

在xenomai中,双内核就是Xenomai的Nucleus/Cobalt Core和Linux内核。

Xenomai改变整个系统架构,让ipipe - > xenomai scheduler来预先处理实时任务,而Linux则拉到上层成为一个任务。这样可以避免Linux因为庞大的架构而影响处理实时的时间。

一、Xenomai系统架构

xenomai的软件版本已经由2.xx版本过渡到3.xx,架构发生了较大变化,主要在实时内核不再是原来的Adeos,改由现在的cobalt。

以下是Xenomai 应用架构。

Xenomai是一个linux内核的补丁藉由在底层增加一个架构负责硬体与接收中断并将中断传给上层的OS(这边称为域)。Xenomai的两个域:

域1:Xenomai。调度核心(scheduler)为Nucleus/Cobalt,应用接口为Skin。xenomai2的调度器为Nucleus,xenomai3的调度器为Cobalt。

域2:Linux。调度核心(scheduler)为Linux原生,应用接口为Linux原生。这个底层的架构Adeos是另一个开源的项目。

二、Xenomai的特性

Xenomai 具有良好的移植性和兼容性

Xenomai 曾经一度与 RTAI 合并为一个项目,但最终还是分化为两个不同的开源项目,最重要的原因还是两者的根本目标不一致。RTAI 的目标是尽可能提高操作系统的实时性,为之牺牲其他的特性(包括可移植性和兼容性)也是可以接受的。与之相反,Xenomai 则是为了提高系统的以及实时任务程序的可移植性和兼容性,可以在一定程度上弱化对操作系统实时性的要求。由于 Xenomai 所提供的实时性能已经足以应付绝大部分的实时任务需求。而 Xenomai 对可移植性和兼容性的坚持能为笔者在实现过程中提供很大的便利。

Xenomai 拥有丰富的实时API

Xenomai 将自己的 API 称为皮肤(Skin),这是一个非常生动的比喻。

如图所示,在实时核心之外,Xenomai 拥有一整套可以与之交户的 API。这些 API 像皮肤一样覆盖在实时核心的表面。这些“皮肤”不仅仅局限于上面的四种,还包括 VRTX 、pSOS+、μITRON、RTDM等等。这些“皮肤 ”通过不同的函数库构造,但都可以被用于Xenomai 。

这样一来,原本为其它实时操作系统所设计的应用都能够很方便地移植到 Xenomai 上。而这也降低了 Xenomai 应用开发的难度,以及应用在不同硬件平台间移植的难度。

Xenomai 对各种硬件架构保持了广泛的支持,例如:ARM,AARCH64,PowerPC/32,x86。对硬件的广泛支持使 Xenomai 能适应于多种嵌入式环境,扩大了 Xenomai 的应用范围。

三、操作系统可适应域环境

操作系统可适应域环境(Adeos,Adaptive Domain Environment for Operating Systems)是一个可以作为 Linux 内核 patch 使用的资源虚拟层,主要设计由 KarimYaghmour 在 2001 年提出 。

就像 Linux 全称应该是 GNU/Linux 一样,RTAI 和 Xenomai 的全称也应该是 Adeos/RTAI 和Adeos/Xenomai。Xenomai 基于 Adeos 实现双内核机制,下图 显示了 Xenomai、Adeos 和 Linux这三个软件实体之间的相互关系。Adeos 是扩展 Linux 的基础环境,有必要对其做一个较详细的介绍。

Adeos 是一个简单有效的实时系统框架,提供了在同一套硬件上同时运行 GNU/Linux 和RTOS 的途径。为了实现这个功能,Adoes 在同一套硬件上提供了多个域(domain)。这些域彼此独立,都无需知道彼此的存在,只需要能够与 Adeos 通信。一个域通常包含了一个完整的操作系统,但是并不局限于此。但是,所有的域都有能力根据被赋予的系统优先级,处理外部事件(例如中断)或是内部事件(例如陷阱和异常)。

Adeos另一个优势是,无论底层的硬件如何变化,它都对在其上运行的域提供一整套通用的 API。这样,系统的移植工作就几乎完全取决于Adeos的移植,而与上层的客户域没有任何关系。

作为为上层RTOS提供基础的Adeos,包含了一系列基础特性:

  • 事件管道

Adeos的一个基本结构是基于事件控制关系链的客户域。域是基于内核的软件组件,它能够要求 Adeos 层告知以下的事件:

每一个外部中断,或自动产生的虚拟中断;

每一个Linux应用申请的系统调用;

其它由内核代码产生的系统事件(例如 Linux 任务交换,信号通知,Linux 任务推出等等)

Adeos确保事件能有序地排列好,并依次传递给系统中对应优先级的域。因此,事件的传递时间是可以严格可预估的。通过给域分配恰当的优先级,事件的传递顺序可以明确得知。

Adeos的域都根据它们各自的优先级从高到低排序,形成了Adeos中控制事件流向的“事件管道”。事件(包括中断)从事件管道的头部(优先级最高)处进入,依次执行到事件管道的尾部(优先级最低)。下图给出了基于 Adeos 的系统的事件处理流程。

在上图中,Linux 内核在事件管道中的位置可以变动。然而,Linux内核作为根域仍然具有重要的作用,因为其它域都需要Linux来对它们进行安装,通常是作为Linux内核模块的方式加载。

  • 主动中断保护

为了在允许域创建可中断过程的同时能够有序地发送中断,Adeos 实现了一种主动中断保护机制。

事件管道处理到某个域时的状态被称作延阻(stalled),在这种状态下下一个到来的中断不会被提交给域处理器,也自然不会被顺着事件管道流转到最低优先级的域。在延阻状态,被阻塞的中断会被记录在中断日志中,最终会在接触延阻状态时被一个称为同步(synchronization)的操作处理。域通过这种特性来保护各自的临界区不被自己的中断处理程序意外抢占。得益于 Adeos 的虚拟化中断,更高优先级的域仍然能收到中断,并抢占低优先级的域。这就是说,基于 Adeos 的系统能通过延阻来保护当前域的临界操作,但是处于事件管道前列,并且优先级高于当前域的实时系统域仍然能够无阻碍的接受中断,而不会有任何额外的延迟。

当一个域处理完所有阻塞的中断,它会通过一个特殊的Adeos系统服务将CPU交给在事件管道中的下一个域,以便后面的域能依次处理这些阻塞的事件,直到最后一个优先级最低的域。

下图说明在在多CPU的情况下,各个域是如何通过 Adeos 的事件管道共享中断的。当然,当一个域进入延阻状态时对阻塞中断的记录是必须的,这部分工作由各域对应的各CPU的单独的日志完成。

系统事件传递

中断不是唯一可以通过事件管道传递的事件,由 Linux 内核自身或者 Linux 应用程序产生的叫做系统事件的内部事件同样也可以。通常,系统事件是由陷阱、异常或者是由 Linux 内核活动产生的同步通知,并被管道内的某些部分所获取。

正因为这些事件本质上是同步的,延阻不能阻碍这些事件的传递。这样设计的原因是,如果系统事件不能得到立刻处理,相关代码就可能无法继续执行。例如页错误处理程序在内存分配异常之后必须立刻执行,推迟它没有任何意义。换句话说,延阻/取消延阻的操作只影响中断,无论是实际中断或是虚拟中断。

四、Adeos与Xenomai

要说明 Adeos 与 Xenomai 之间的关系,只需要回答“Adeos 为 Xenomai 提供了什么”这样一个问题。同样的,这个问题也可以被表述成:Xenomai 为了提供实时服务需要哪些基本保证?答案十分简单直接:它必须在 Linux 内核得知中断之前首先处理中断,并且无论 Linux内核是否通过 CPU 中断掩码屏蔽中断都必须立刻处理中断。它也必须无视线程当前所在的执行域,始终执行根据恰当优先级的线程管理。

这些保证使得 Xenoami 能够准确给出微秒级的中断时延预测,不论 Linux 在执行什么活动。通过 Xenomai 快速的对 Linux 任务的协作调度技术,为实时线程提供了可预测的抢占时延。

下图给出了 Adeos 在 Xenomai 架构中的位置。

注意到,Adeos 接口直接提供给 Xenomai 核下的硬件抽象层。因此,大部分对 Adeos 提起 的 服务 请 求都 来自于 硬件 抽象层。 相关的实现都 可以从 Xenomai 源码的对应arch/<archname>/hal 目录下找到,而通用的实现则在 arch/generic/hal 目录下。

  • Xenomai 的主域和次域

Xenomai 可以在内核空间运行实时线程,也可以在 Linux 普通进程空间运行实时线程。所有由 Xenomai 管理的线程都工作在实时核之上。

对实时线程在内核空间的支持继承于纯粹的双内核实现方式。在真正提供用户空间实时支持之前,实时应用只能作为内核模块被运行。这个特性在 Xenomai 中得到了保留,用以支持之前的实时应用。

Xenomai更有趣的是向标准 Linux 的靠近,这也是它区别于 RTAI/LXRT 实现方式的原因。

为了实现这一点,Xenomai 线程不仅能够在事件管道中的高优先级域(主域)内的上下文中执行(就像基于内核的 Xenomai 线程),也能在通常的 Linux 空间(从域)内执行。在从域内的 Xenomai线程仍然被 Xenomai 认为是实时的,虽然会遭受一些调度时延的损失。用 Xenomai 的术语来说,前一种执行方式被称为主执行模式,后一种被称为从执行模式。

为了在从域中能够提供完全的实时性支持,Xenomai 需要达成以下的条件:

1)通用的优先级规划。对于实时核心和 Linux 内核都具有控制权的线程,两者需要有同样的优先级规划。换句话说,Xenomai 线程需要具有无论运行于什么域,都能根据其优先级来执行的能力。Xenoami 运用了被称之为“根线程可变优先级(rootthread ’ smutablepriority)”的技术,来使由实时核心控制的 Xenomai 线程在进入从域时由 Linux 内核自动继承其优先级。实际上,这就意味着在主域运行的 Xenomai 线程不会抢占在从域中运行的 Xenomai 线程,除非前者的优先级高于后者。这种模式与 RTAI/LXRT 不同,RTAI/LXRT 的线程在进入Linux空间时会失去原有的优先级,转而被 RTAI 的调度器标记为最低的优先级。这就是说,常规的Linux 任务对于 Xenomai 来说是不可见的,只属于SCHED_FIFO 类,而且在与主域的 Xenomai线程竞争时永远会被抢占。虽然两者同时在从域时可以根据优先级公平竞争。

2)程序执行时间的可预测性。当一个Xenomai线程在Linux 域执行时,无论它在执行内核代码还是应用代码,都不应该被非实时的 Linux 的中断活动或是其他的异步内核活动中断。

一个能够简单地达成这个目标的方法是,在 Xenomai 线程运行于 Linux 域的时间段内,不给Linux 内核提供中断。这样一来,就不会有任何造成延迟的中断处理程序上半部会被触发。一个简单的组织向 Linux 内核提供中断的方法是,在需要时在一个介于实时核心域和 Linux 内核域的中间域中屏蔽中断。这个域用 Xenomai 术语来说叫做中断屏障(interruptshield)。这个屏障在 Xenomai 线程受 Linux 内核调度时启用,在其他状态下则停用。这个屏障在 Xenomai建立时可以设定对单一线程有效,也可以对系统内所有 Xenomai 线程有效,默认配置是对所有 Xenoami 线程都不启用。

3)小体积的 Linux 内核。为了在从执行模式下获得最好的效果,需要 Linux 内核有尽量少的不可抢占区域,以便于 Xenomai 线程在从域中可以执行时能尽快获得调度机会。另外,这也会减少 Xenomai 线程从主域转移到从域的时间,因为这个操作同样需要在调度点才能够执行。正因为如此,Xenomai 也会从类似于 IngoMolnar  sPREEMPT_RT 扩展对内核可抢占性的提升中受益。当然,只运行在主域的 Xenomai 线程不会受 Linux 内核的影响,总是会获得很低的延迟。因为它们不必受限于 Linux 操作,总是有无条件的抢占权。

4)优先级反转管理。不管是实时核心还是 Linux 内核都需要防止高优先级的线程因为无法获得低优先级线程所占有的资源而无法运行。Xenomai 可以为实时核心解决这个问题,但是Linux 内核需要 PREEMPT_RT 扩展来实现。因为这个原因,Xenomai 提供对 PREEMPT_RT的支持。

由于以上种种条件的要求,当 Xenomai 核被加载时,底层的 Adeos 管道会经历三个阶段 ,而所有的中断都会按优先级在管道中流过。这三个阶段分别是:Xenomai 主域,即实时核心域;中断屏障域;Linux 域;如图所示。

  • 系统调用拦截

因为在 Xenomai 核心上的实时 API(即皮肤 skin,会在下文加以说明)可以在用户空间给Xenomai 线程提供服务,必须存在一种方式可以将对应的系统调用以及常规 Linux 内核的系统调用都提交给恰当的处理程序的机制。为了完成这个目标,Xenomai 通过 Xenomai 线程拦截每个系统陷阱和异常,无论来自 Xenomai 域还是 Linux 域。通过用 Adeos 服务来登记每个时间处理器,Xenomai 完成了这样的拦截。Xenomai 用这个能力完成了以下的功能:

将来自应用的实时服务请求传递给对应的系统调用处理器,而这些处理器由实时核心上不同的 API 来实现。

确保每个系统调用都由恰当的域来控制,无论是 Xenomai 域或是 Linux 域。这个操作是通过将调用者无缝地转移到目标域来实现的。举例来说,一个来自运行于 Xenomai 域的Xenomai 线程的 Linux 系统调用,会在请求到达常规 Linux 系统处理之前,将 Xenomai 线程转移到 Linux 域。相对的,一个 Xenomai 线程提出一个 Xenomai 阻塞系统调用的话,它也会被转移到 Xenomai 域。因此,这个线程能够在实时核心的控制下进入睡眠状态。

以上两者的结合使得 Xenomai 线程可以完整地进入 Linux 的国度。举例来说,一个对Xenomai 的系统调用可以看作是 Linux 的扩展。为了更好地证明这一点,Xenomai 线程完全支持 Linux 的信号以及跟踪(ptrace)特性,而这又使 GDB 能够原生地 Xenomai 线程。

  • 中断传播

因为出于管道的头部,在 Xenomai 域中的实时核心总能在中断到来时第一个得知,并对中断进行处理,在对中断进行适当标记后通过管道向下传递,在需要的情况下最终传递到Linux 域。

当获得一个中断时,实时核心在外部中断处理程序返回后执行调度(防止中断堆积),并转而执行优先级最高的可运行线程。

Xenomai 域在没有实时活动阻塞时将 CPU 交给中断屏障域,而中断屏障域则根据是否启用中断屏障来决定是否将中断传递给 Linux 内核。

对于中断传递,Adeos 有两种基本模式:

隐式传递,任何中断在进入接受域时,都被 Adeos 在接受域的日志中自动标记为被阻塞。

显式传递,一个中断在需要的情况下,必须由中断处理程序“手动”地传递到相邻的域中。

这些设置可以针对各个域或者各个中断分别设置,Xenomai 对它拦截的所有中断都采用显示传递。这就意味着,任何一个中断处理程序,都必须显示地调用中断传递服务来将中断在管道中传递下去。如果 Xenomai 没有对指定的中断提供中断处理程序,该中断将被无条件地传给 Linux 内核。这使得在实时核心没有拦截相关中断时,系统依然能够正常运行。


http://www.ppmy.cn/server/157697.html

相关文章

Mybatis中 Dao接口和XML文件的SQL如何建立关联

建立连接工作&#xff08;准备&#xff09;: 首先会加载Myatis的配置文件&#xff0c;因为这些配置文件里面包括了数据源的各种配置&#xff0c;然后通过SqlSessionFactory创建一个SqlSession&#xff0c;然后可以通过SqlSession操作数据库。 一、解析XML: 首先&#xff0c;…

Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例

Android车机DIY开发之学习篇(二)编译Kernel以正点原子为例 1.代码在/kernel-5.10文件夹下 2.在kernel-5.10目录下执行如下命令编译 &#xff1a; 编译之前&#xff0c;需要将 clang 导出到 PATH 环境变量&#xff1a; 如果是 Android12 执行下面这条命令 export PATH../pr…

doris:手动分区

分区列​ 分区列可以指定一列或多列&#xff0c;分区列必须为 KEY 列。PARTITION 列默认必须为 NOT NULL 列&#xff0c;如果需要使用 NULL 列&#xff0c;应设置 session variable allow_partition_column_nullable true。对于 LIST PARTITION&#xff0c;支持真正的 NULL 分…

Java SE 与 Java EE 简介

诸神缄默不语-个人CSDN博文目录 在学习和使用Java语言时&#xff0c;我们常常会遇到两个常见的术语&#xff1a;Java SE 和 Java EE。它们分别代表了Java的不同应用层次和开发领域。本文将深入介绍Java SE和Java EE的区别、特点以及适用场景&#xff0c;帮助大家更好地理解这两…

js代理模式

允许在不改变原始对象的情况下&#xff0c;通过代理对象来访问原始对象。代理对象可以在访问原始对象之前或之后&#xff0c;添加一些额外的逻辑或功能。 科学上网过程 一般情况下,在访问国外的网站,会显示无法访问 因为在dns解析过程,这些ip被禁止解析,所以显示无法访问 引…

7 分布式定时任务调度框架

先简单介绍下分布式定时任务调度框架的使用场景和功能和架构&#xff0c;然后再介绍世面上常见的产品 我们在大型的复杂的系统下&#xff0c;会有大量的跑批&#xff0c;定时任务的功能&#xff0c;如果在独立的子项目中单独去处理这些任务&#xff0c;随着业务的复杂度的提高…

B+树在MySQL中的应用价值

为什么MySQL选择B树存储数据 在数据库管理系统中&#xff0c;存储和查询数据的效率直接影响系统的性能。MySQL 作为最常用的关系型数据库之一&#xff0c;其存储引擎&#xff08;例如 InnoDB&#xff09;选择了 B 树作为索引的数据结构。这种选择并非偶然&#xff0c;而是经过…

Java基础:equals()方法与==的区别

1、超类Object的equals()底层原理&#xff1a; 在Object超类中已经提供了equals()方法&#xff0c;源码如下&#xff1a; public boolean equals(Object obj) { return (this obj); } 所有的对象都拥有标识&#xff08;内存地址&#xff09;和状态&#xff08;数据&a…