您的位置:首页 > 其它

(转)为提高实时性能,设计和优化 Microsoft Windows CE .NET(上)

2009-04-24 11:46 477 查看
(转)为提高实时性能,设计和优化 Microsoft Windows CE .NET(上)
摘要:本文从技术角度详细描述了为了增强实时性能特征而设计的对 Microsoft Windows CE 操作系统 (OS) 作出的更改。它还讨论了可用于测试实时性能的工具,并提供了特定硬件配置的有代表性的实时性能测试结果。



本页内容


简介


对内核的更改


实时测量工具


性能测量


小结

简介

对于高性能的嵌入式应用程序所需要的对时间要求严格的响应来说,实时性能是不可缺少的,例如,电信交换设备、工业自动化和控制系统、医学监视设备和空间导航和制导系统。这样的应用程序必须在指定的时间参数以内实时地传递它们的响应。

实时性能是什么?对于 Microsoft Windows CE .NET OS,以下列表定义了实时性能:

有关高优先级线程调度的担保的上限 — 只针对所有已调度线程中的最高优先级线程。

调度高优先级中断服务例程 (ISR) 过程中有关延迟的担保上限。抢占机制在一个短暂、有限的时间内关闭后内核有很少的空间。

对计划程序和它如何调度线程进行细致的控制。

重要的是应当区分实时系统和实时 OS (RTOS)。实时系统由满足系统要求所需的所有元素(硬件、OS 和应用程序)组成。RTOS 只是完整的实时系统的一个元素,它必须提供足够的功能,才能使全部实时系统能够满足它的要求。

尽管以前的 Windows CE 版本提供了某些 RTOS 功能,但自从 Windows CE 3.0 以后很多重要的内核更改极大地增强了实时性能。Windows CE .NET 内核包含了与 Windows CE 3.0 相同的实时增强功能,除此之外还有某些额外的功能。本文描述了作为 Windows CE .NET 及其以前版本的组成部分的以下更改:

Windows CE .NET

对 x86 平台添加了通过 OEM 定义的变量指定页面池大小的功能。

Windows CE 3.0

增加了线程优先级级别的数目(从 8 到 256)。

更多地控制时间和调度。应用程序可以控制提供给每个线程的时间,并操纵对它们有好处的计划程序。现在,对于与休眠和等待相关的应用程序编程接口 (API),计时器精确到一毫秒。

处理优先级倒置的方法得到改进。

全面支持嵌套中断。

ISR 和中断服务线程 (IST) 滞后时间得到减少。

更细粒度的内存管理控制。

此外,本文描述了用来测试内核实时性能的工具,并提供了在三种不同 CPU 上的实时性能测试结果。



返回页首

对内核的更改

内核是 Windows CE OS 的内部核心,它负责调度和同步线程、处理异常和中断、加载应用程序和管理虚拟内存。在 Windows CE 3.0 中,为了提高性能和减少滞后时间,内核经历了以下几个更改:

将所有内核数据结构移动到物理内存,从而当在内核中执行非抢占代码时极大地避免了转换后备缓冲区 (TLB) 损失。

所有非抢占、但可中断的内核部分(称为 KCALL)被分割成更小的非抢占节。由于增加了节数,这就引入了某些复杂性,但现在抢占机制能够在更短的时间内关闭。

这一节描述为了增强 Windows CE 3.0 的实时性能对内核的进一步更改。

更多优先级级别

内核的计划程序首先使用较高的优先级级别运行某个线程,然后使用相同的优先级以循环方式运行多个线程。为线程指派优先级级别是管理执行速度的一种方式。

Windows CE 3.0 将可用于线程的优先级级别数从 8 增加到 256,0 是最高的优先级,255 是最低的优先级。Windows CE 的前一版本的优先级级别 0 到 7 对应于 Windows CE 3.0 中级别 248 到 255。更多的优先级级别允许开发人员更灵活地控制嵌入式系统的调度,并防止由于限制优先级级别数使随机应用程序降低系统性能。

要指派这些新的优先级,Windows CE 3.0 引入了两个新函数:CeSetThreadPriorityCeGetThreadPriority。新函数与 Windows CE 2.12 中的 SetThreadPriorityGetThreadPriority 函数看起来完全相同,不过新函数接受的数字范围是 0 到 255。

更多地控制时间和调度

Windows CE 3.0 已经改进了计时器性能,计时器和休眠函数调用的精度达到了一毫秒,并且应用程序可以为每个线程设置时间片。

计时器(或系统时钟)是一种速率,由 OS 以此速率生成计时器中断并对其提供服务。以前,计时器也是线程时间片,是线程没有被抢占的情况下可以在系统中运行的最长时间。在 Windows CE 3.0 中,计时器不再直接与线程时间片相关。

以前,OEM 将计时器和时间片作为 OEM 适配层 (OAL) 中的常量设置为大约 25 毫秒。计时器触发时,如果一个线程已做好准备,内核会调度此新的线程。在 Windows CE 3.0 中,计时器总是设置为一毫秒,并且可以对每个线程设置时间片。

通过将计时器从 OEM 定义的数字更改为一毫秒,可以让应用程序执行 Sleep(1) 函数,并预计得到大约一毫秒的精度。当然,这取决于线程的优先级、其他线程的优先级以及是否正在运行 ISR。以前,Sleep(1) 经过一个系统周期后返回,这意味着如果计时器被设置为 25 毫秒,则 Sleep(1) 实际上是 Sleep(25)

计时器中断

现在,内核有几个新的变量,开发人员可以使用它们确定系统时钟是否需要重新调度。通过在适当的时候返回 SYSINTR_NOP 标志而不是 SYSINTR_RESCHED 标志,完整实现的系统时钟 ISR 可以防止内核被重新调度。Nk.lib 导出在 Timer ISR 中使用的以下变量:

dwPreempt 是线程被抢占之前的毫秒数。

dwSleepMin 是第一次超时(如果有)到期之前的毫秒数,需要重新调度。

ticksleft 是已经过去、但尚未被计划程序的休眠队列处理的系统时钟数;因而,非零值将导致重新调度。

在 Timer ISR 中,其他逻辑将优化计划程序,并防止内核执行不必要的工作,如以下代码示例所示。

if (ticksleft || (dwSleepMin && (DiffMSec >= dwSleepMin)) || (dwPreempt && 
      (DiffMSec >= dwPreempt))) return SYSINTR_RESCHED; return SYSINTR_NOP;

OEMIdle 函数

OEM 实现 OEMIdle 函数,在没有要调度的线程时内核将调用该函数。在以前的版本中,计时器时钟会强制 OS 脱离空闲状态,并返回到内核以确定是否线程已做好调度准备。如果没有线程做好准备,内核再次调用 OEMIdle。该操作将导致内核每隔 25 毫秒(或 OEM 指定的其他时间片长度)被激活一次,以确定是否仍然没有要调度的线程。在电池供电的设备上,这样的操作会耗尽宝贵的电池电量。

在 Windows CE 3.0 中,为了在时钟频率较高的情况下减少耗电量,OEMIdle 函数可以让 CPU 进入待机模式一毫秒以上。OEM 通过使用 dwSleepMinDiffMSec 变量来编程设置系统时钟计时器,以便在第一个可用的超时后唤醒。DiffMSec 是自从通过 TimerCallBack 函数检索到最后一次间隔时间以来的当前毫秒值。

硬件计时器的最大超时值可能小于 MAX_DWORD 毫秒值,所以可以编程设置计时器的最大等待时间。在所有情况下,系统从空闲状态返回时,OEMIdle 函数必须使用已经过去的实际毫秒数更新 CurMSecDiffMSecCurMSec 是间隔时间的当前值 £­ 即自从启动以来的毫秒数。

线程时间片

在 Windows CE 3.0 中,线程时间片很灵活,足以使应用程序能够逐个线程地设置时间片。这就让开发人员可以改编计划程序,以满足应用程序的当前需要。为了调整时间片,已经添加了两个新函数:CeGetThreadQuantumCeSetThreadQuantum。这项更改使应用程序能够基于线程完成任务所需要的时间量来设置线程的时间片。通过将任何线程的线程时间片设置为零,循环调度算法可以变为“运行到完成”算法。只有较高优先级的线程或硬件中断才能先于设置为运行到完成的线程执行。

默认时间片是 100 毫秒,但在 OEM 初始化阶段,OEM 可以通过将内核变量 dwDefaultThreadQuantum 设置为大于零的任何值,从而重写系统的默认值。

更改处理优先级倒置的方法

为了有助于缩短响应时间,Windows CE 3.0 更改了它的优先级倒置方法,当低优先级线程拥有一个较高优先级线程所需要的内核对象时,就会发生优先级倒置。Windows CE 使用优先级继承来处理优先级倒置,这时,被阻塞的、拥有较高优先级线程所需要的内核对象的线程将继承更高的优先级。优先级倒置使较低优先级线程能够运行,并释放资源供较高优先级的线程使用。以前,内核处理整个倒置链。从 Windows CE 3.0 开始,内核保证只处理优先级倒置到一个级别的深度。

优先级倒置有两个基本示例。第一个是简单的情况,这种情况下,对优先级倒置的处理从 Windows CE 2.12 到 Windows CE 3.0 没有变化。例如,在有三个处于运行状态的线程时,可以看见这种情况。线程 A 的优先级是 1,线程 B 和 C 优先级较低。如果线程 A 正在运行,并且因为线程 B 拥有线程 A 需要的内核对象而使 A 被阻塞,那么线程 B 的优先级会提高到 A 的优先级级别,以便允许线程 B 运行。然后,如果因为线程 C 拥有线程 B 需要的内核对象而使线程 B 被阻塞,则线程 C 的优先级会提高到 A 的优先级级别,以便允许线程 C 也能运行。

第二个并且是更有趣的情况是,线程 A 可以以比 B 和 C 更高的优先级运行,线程 B 拥有 A 需要的内核对象,线程 B 被阻塞,等待 C 释放它需要的内核对象,而 C 正在运行。在 Windows CE 2.12 中,当 A 运行然后因为 B 而被阻塞时,B 和 C 的优先级都会提高到 A 的优先级,以便使它们能够运行。在 Windows CE 3.0 中,当 A 因为 B 而被阻塞时,只有线程 B 的优先级被提高。通过减少复杂性和更改算法,极大地减少和限制了 Windows CE 中最大的 KCALL。

中断处理和嵌套中断

实时应用程序使用中断作为确保 OS 快速地注意外部事件的方式。在 Windows CE 内,内核和 OAL 经过调整,以便优化对系统的其余部分的中断传递和事件调度。Windows CE 通过将中断处理拆分为下面两个步骤,对性能与实现的容易性进行平衡:中断服务例程 (ISR) 和中断服务线程 (IST)。

每个硬件中断请求线 (IRQ) 都与一个 ISR 相关。允许中断并出现中断时,内核会调用该中断的注册 ISR。ISR 作为中断处理的内核模式部分,将尽可能保持简短。它的责任主要是指引内核启动适当的 IST。

ISR 执行最低程度的处理,并向内核返回中断标识符。内核检查返回的中断标识符,并设置将 ISR 链接到 IST 的相关事件。IST 等待该事件。内核设置事件时,如果 IST 是准备运行的最高优先级线程,IST 将停止等待,并开始执行它的其他中断处理。大多数中断处理实际上发生在 IST 以内。

嵌套中断

在 Windows CE 3.0 以前的版本中,ISR 正在运行时,所有其他中断都会关闭。这将使内核无法处理任何其他中断,直到一个 ISR 已经完成为止。所以如果高优先级中断已做好准备,内核不会处理新的中断,直到当前的 ISR 已经完成操作并返回到内核为止。

为了防止高优先级中断丢失和延迟,Windows CE 3.0 基于优先级添加了对嵌套中断的支持(如果 CPU 或其他相关硬件支持它)。ISR 在 Windows CE 3.0 中运行时,内核将像以前一样运行指定的 ISR,只是禁用了相同和较低优先级的 ISR。如果较高优先级的 ISR 做好运行准备,内核将保存正在运行的 ISR 的状态,并让较高优先级的 ISR 运行。内核可以嵌套 CPU 可支持的最大数量的 ISR。ISR 按硬件优先级的顺序进行嵌套。

大多数情况下,OEM 的当前 ISR 代码不会更改,因为由内核处理详细信息。如果 OEM 在 ISR 之间共享全局变量,则可能需要进行更改,但通常,ISR 不知道它们已经被较高优先级的 ISR 所中断。如果 ISR 定期地执行操作,则可能会发生显而易见的延迟,但延迟只有当较高优先级的 IRQ 被触发时才会发生。

最高优先级的 ISR 结束之后,将执行任何挂起的较低优先级的 ISR。然后,内核继续处理任何被中断的 KCALL。如果线程正在被调度并在 KCALL 中间被中断,则计划程序会继续处理线程。这将使内核能够从它停止的地方继续执行,而不用完全重新启动对线程的调度,从而节约了宝贵的时间。一旦挂起的 KCALL 完成操作,内核将重新调度线程的执行,并开始执行做好运行准备的最高优先级的线程。

中断滞后时间

内核实时性能的一个最重要的特性是能够在指定的时间内服务 IRQ。中断滞后时间主要是指软件中断处理滞后时间 £­ 即从外部中断到达处理器的时间直到中断处理开始的时间所经过的时间。

如果不发生分页操作,Windows CE 3.0 中断滞后时间被限制于内存中锁定的线程。这样就可以计算最糟糕情况下的滞后时间 £­ 到 ISR 的启动和到 IST 的启动的总计时间。然后,在中断被处理以前的时间总量可以通过计算在 ISR 和 IST 中所需要的时间来确定。

ISR 滞后时间

ISR 滞后时间是从 IRQ 在 CPU 中被设置时到 ISR 开始运行时的时间。以下三个与时间相关的变量会影响 ISR 的启动:

A 中断在内核中关闭的最长时间。内核很少关闭中断,但如果将它们关闭,则关闭的时间长度会受到限制。

B 在内核调度中断和 ISR 被实际调用之间的时间。内核使用该时间确定要运行什么 ISR,并保存在继续之前必须保存的任何寄存器。

C 在 ISR 返回到内核和内核实际停止处理中断之间的时间。这是内核通过还原在 ISR 被调用之前被保存的任何状态(例如寄存器)来完成 ISR 操作的时间。

正在测量的 ISR 的启动时间可以基于系统中其他中断的当前状态进行计算。如果中断正在进行,则计算要测量的新 ISR 的启动时间必须考虑到两个因素:所关注的中断已经发生之后将发生的较高优先级中断的数量,以及执行 ISR 所占用的时间。以下示例说明了所得到的启动时间。

Start of ISR =





这里,NISR 是将在已发生所关注的中断之后发生的较高优先级中断的数量;TISR(N) 是执行 ISR 所需要的时间。下面的图 1 说明了该公式。



1. ISR 启动时间公式的图形表示

如果没有发生较高优先级中断 (NISR=0),则前面的公式将简化为以下的代码示例。

Start of ISR = A + B

Windows CE 和 OEM 都会影响执行 ISR 的时间。Windows CE 控制变量 A、B 和 C,它们都会受到限制。OEM 控制 NISR 和 TISR(N),它们都可以极大地影响 ISR 滞后时间。

IST 滞后时间

IST 滞后时间是从 ISR 完成执行(即通知线程)到 IST 开始执行的时间。以下四个与时间相关的变量会影响 IST 的启动时间:

B 内核调度中断和 ISR 被实际调用之间的时间。内核使用该时间确定要运行什么 ISR,并保存在继续之前必须保存的任何寄存器。

C 在 ISR 返回到内核和内核实际停止处理中断之间的时间。这是内核通过还原在 ISR 被调用之前保存的任何状态(例如寄存器)来完成 ISR 操作的时间。

L KCALL 中的最长时间。

M 调度线程的时间。

在 ISR 返回到内核并且内核执行某些工作来开始执行 IST 之后最高优先级 IST 开始的启动时间。在 ISR 返回并通知 IST 开始运行之后,IST 启动时间受所有 ISR 的总计时间的影响。下面的示例说明了所得到的启动时间。

Start of highest priority IST =





下图说明了该公式。



2. 最高优先级 IST 启动时间公式的图形表示

Windows CE 和 OEM 都会影响执行 IST 所需的时间。Windows CE 控制变量 B、C、L 和 M,它们都是受限制的。OEM 控制 NISR 和 TISR(N),它们可以极大影响 IST 滞后时间。

Windows CE 3.0 还对 IST 添加了以下限制:链接 ISR 和 IST 的事件处理只能用在 WaitForSingleObject 函数中。Windows CE 3.0 防止 ISR-IST 事件处理被用在 WaitForMultipleObjects 函数中,这意味着内核可以担保触发事件的时间和释放 IST 的时间有一个上限。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: