Java的实时规范
新语言、编程规程、操作系统和软件工程技术有时对实时软件开发人员具有相当大的潜力。面向对象编程是一个有希望的领域,但对实时社区来说,这是一个相当新的领域。
例如,Java大量地从面向对象中提取,并且非常适合于对实时和嵌入式系统的扩展,在Java社区过程中,Java专家小组(RTJEG)在1999年3月开始开发Java(RTSJ)1的实时规范。
RTJEG的目标是提供一个平台——Java执行环境和应用程序接口(API)——让程序员正确地推断出执行软件的时间行为。编写实时系统应用程序的程序员必须能够在某些逻辑执行的时候确定一个先验,并在某个期限之前完成它的执行。这种可预测性在许多实时系统应用中很重要,例如飞机控制系统、军事指挥和控制系统、工业自动化系统、交通和电话交换机。我们通过查看Java语言特异性和Java虚拟机规范来开始我们的工作。对于语言或运行时代码的每个特性,我们询问声明的语义是否会让程序员在执行过程中,在执行之前,让程序员以合理的努力来决定,然后执行该特性(或特性控制的特性)的时间行为。RTSJ提供了一个平台,让程序员能够正确地推断出执行软件的时间行为。Java专家小组的两个实时成员解释了RTSJ的特性以及规范设计背后的思想。Greg Bollella IBM的James Gosling Sun Microsystems公司整顿了三个特性——调度、内存管理和同步——这并不允许这样的决定。由国家科学技术研究院(NIST)主办的研讨会上定义的需求与其他行业组织的投入帮助我们确定了附加的特征和语义。我们决定将其中的四个附加特性包括:异步事件处理、异步控制传输、异步线程终止以及对物理内存的访问。
这些加上我们对Java和JVM规范的回顾,为RTSJ提供了七个主要区域。我们相信这七个领域提供了一个适合广泛应用的实时软件开发平台。“RTSJ如何达到它的目标?”边栏给出了驱动RTSJ开发的需求和原则的更多背景。“RTSJ时间表”边栏列出了那些有兴趣审查草案的人的重要里程碑和联系。RTSJ在2000年2月完成了公共审查,但是Java社区过程要求我们在完成参考实现和测试套件之前不确定规范。随着社区获得RTSJ的经验,对规范的微小更改可能会发生。我们写这篇文章的目的是为了深入了解RTSJ的设计理念——特别是NIST的需求和其他的目标是如何影响它的——并说明这个重要的规范是如何适应于为实时系统开发优化面向对象编程系统的总体战略方向的。
调度Java规范只提供了对调度的广泛指导:在处理资源的竞争中,优先级较高的线程通常优先于低优先级的线程。但是,这样的首选项并不能保证优先级最高的线程始终运行,并且线程优先级不能用于可靠地实现互斥。显然,如果您正在编写具有时间限制的软件,那么您需要对线程执行的顺序有更强的语义声明。定义这些语义的典型方法是通过确定如何选择下一个线程执行的算法。RTSJ指定了一个最小的调度算法,它必须在所有RTSJ实现中。至少,所有实现的最低要求必须提供一个固定优先的优先级调度程序,不少于28个独特的优先级。“固定优先级”意味着系统不改变线程优先级(例如,通过老化)。有一个例外:系统可以将线程优先级更改为执行优先级反转规避算法的一部分(保留优先级继承)。如果没有异常,线程可以更改自己或另一个线程的优先级。
调度Java规范只提供了对调度的广泛指导:当有处理资源的竞争时,具有更高优先级的线程通常会优先选择较低优先级的线程。然而,这样的优先级并不能保证最高优先级的线程总是在运行,而线程优先级不能用于可靠地实现互斥。显然,如果您正在编写带有时间约束的软件,那么您需要一个更强的语义语句来说明线程应该执行的顺序。定义这些语义的典型方法是通过算法来决定如何选择下一个线程来执行。RTSJ指定最小调度算法,必须在所有RTSJ的实现。至少,所有的实现都必须提供一个固定优先级的优先级调度程序,它不少于28个唯一的优先级。“几个”意味着不改变系统线程优先级(例如,通过老化)。有一个例外:系统可以改变线程优先级的执行优先级反转避免算法(保留优先级继承)。毫无例外,线程可以更改它们自己或其他线程的优先级。
应用程序必须将最小28个优先级视为惟一;例如,它必须知道,如果具有更高优先级的线程已经准备好,那么具有较低优先级的线程将永远不会执行。因此,您不能简单地将28个优先级映射为一个较小的数字,因为底层系统。但是,您可以在一个平台上实现RTSJ提供少于28本地优先级。然后,您就可以使用任何可用的方法来提供惟一性的外观。为什么要有28个优先事项?我们之所以选择这个数字,是因为实时调度理论表明,您可以期望有32个优先级的接近最优的调度能力。5我们选择离开四个优先级为其他任务,因为RTSJ可能只有一个系统的一部分,和一些系统只有32本地优先级。当然,您可以将调度算法添加到这个最低要求中。RTSJ提供了三个classes-Scheduler SchedulingParameters,ReleaseParameters-and这些封装时间需求的子类。这些类绑定到可调度的对象(线程或事件处理程序)。所需的调度器,PriorityScheduler类的一个实例,使用这些参数中设定的值对象。
RTSJ线程创建定义RealtimeThread(RT)类来创建线程,居民调度程序执行。RTs可以访问堆上的对象,因此会因为垃圾收集而导致延迟。创建线程的另一种选择是使用RT的子类,NoHeapRealtimeThread。nhrt不能访问任何堆上的对象,这意味着它们可以运行垃圾收集器运行时从垃圾收集(从而避免延误)。nhrt是适合代码非常低公差的不定期的延迟。另一方面,RTs更适合于对较长时间延迟的更宽容的代码。普通Java线程将为没有时间限制的代码进行处理。内存管理一直被认为是垃圾收集内存堆实时编程的一个障碍,因为垃圾收集器,引入了不可预测的延迟。我们希望RTSJ需要实时垃圾收集器的使用,但技术不够先进。相反,RTSJ扩展内存模型来支持内存管理,不干扰实时代码提供确定性行为的能力。这些扩展让你分配两堆外的短期和长期存活的对象进行垃圾回收。也有足够的灵活性来使用熟悉的解决方案,例如预先分配的对象池。内存区域RTSJ介绍内存区域的概念——一个地区以外的内存垃圾回收堆分配对象,您可以使用。内存区域并不是通常意义上的垃圾收集。严格的对内存区域的赋值规则可以防止您创建悬空指针,从而维护Java的指针安全性。在内存区域中分配的对象可能包含对堆中的对象的引用。因此,垃圾收集器必须能够扫描内存堆中对象的引用的堆外保留堆垃圾收集的完整性。这种扫描与为堆构建可达性图不一样。
收集器只是将堆对象的任何引用添加到它的指针集。因为nhrt可以抢占收藏家,他们不能访问或修改任何指针到堆。RTSJ使用抽象类MemoryArea代表内存区域。这个类有三个子类:物理内存、不朽内存和作用域内存。物理内存允许您在具有特定重要特征的内存区域内创建对象,例如附加在非易失性RAM中的内存。不朽的记忆是一个特例。图1显示了使用不朽内存的对象分配如何与使用Java堆的手动分配和自动分配进行比较。传统的编程语言使用手动配置的应用程序逻辑决定了对象的导向的过程往往是耗时且容易出错。一个不朽的内存池和从它分配的所有对象都将一直存在,直到程序终止。在当今的硬实时系统中,不朽的对象分配是常见的做法。有了作用域内存,就不需要传统的垃圾收集和随之而来的延迟。RTSJ实现通过MemoryParameters字段或作用域内存ScopedMemory.enter()方法。作用域内存图1c显示了作用域内存与不朽内存和其他分配规程的比较。作用域内存,在抽象类中实现ScopedMemory,允许您使用内存区域分配和管理对象,或语法范围,范围内分配的任何对象的生命周期。当系统进入一个语法范围时,每次使用“new”都会导致系统从活动内存区域分配内存。当范围终止或系统离开时,系统通常会将内存的引用计数降为0,破坏分配给内部的任何对象,并调用它们的终结器。您也可以嵌套作用域。当系统进入一个嵌套的范围时,它将从与新作用域相关联的内存中获取所有后续的分配。当它退出嵌套范围时,系统将恢复先前的作用域,并再次从该范围获取所有后续的分配。两个具体子类可用于实例化MemoryAreas:LTMemory(LT的线性时间)和VTMemory变量时间(VT)。在这种情况下,“time”指的是分配新对象的成本。LTMemory要求分配有一个时间成本的线性对象大小(忽略性能变化从硬件缓存或类似的优化)。
当您创建它时,您指定了LTMemory区域的大小,并且它的大小仍然是固定的。虽然VTMemory没有这样的时间限制,您可能想要强加一些限制无论如何变化分配成本降到最低。你建立VTMemory区域初始大小和指定一个最大尺寸它可以生长。你也可以选择执行实时垃圾收集在VTMemory地区,尽管RTSJ不要求。如果你决定这样做,您可以构建VTMemory对象的垃圾收集对象指定一个特定于实现的垃圾收集机制。然而,如果你实现VTMemory,nhrt必须能够使用它。因为,如图1c所示,控制流控制在作用域内存区域中分配的对象的生命,您必须限制对这些对象的引用。RTSJ使用受限制的组分配规则,防止长期对象引用对象作用域内存,可能短住。虚拟机必须检测非法的分配尝试,并在发生时抛出一个适当的异常。RTSJ实现在两个不同的作用域内存机制,持续互动:ScopedMemory.enter()方法和内存区域的MemoryParameters领域。您在创建线程时指定任何一个。因此,几个相关的线程可以共享一个内存区域,并且该区域将保持活动状态,直到最后一个线程退出。这种灵活性意味着应用程序可以从具有适合整个应用程序或特定代码区域的特征的内存区域中分配新对象。同步的同步,RTSJ使用“优先级”比传统的更松散实时文学。“最高优先级的线程”只是表示最合格的线程调度程序会选择从所有的线程可以运行。它不一定认为严格的基于优先级的调度机制。等待队列系统必须排队等待以优先顺序获取资源的所有线程。
这些资源包括处理器和同步块。如果活动调度策略允许具有相同优先级的线程,那么线程将首先在队列中排队。具体来说,系统图1。不朽和作用域内存与其他确定对象生命的方法是不同的。(一)Java堆使用自动分配,可见性决定了对象的生活(如果没有对象的引用,该系统可以释放)。然而,自动分配需要一个垃圾收集器,这会导致延迟。(b)在使用RTSJ不朽内存分配,对象的生命结束只有当Java虚拟机(JVM)终止。(c)RTSJ作用域内存的使用语法范围,一种特殊类型的内存区域外的垃圾收集堆允许您管理对象定义良好的一生。当控制到达逻辑的某个点时,系统会破坏其中的任何对象,并调用它们的终结器。
为了避免优先级反转,同步原语的实现必须有一个默认的行为,以确保没有无限的优先级反转。这适用于普通Java代码如果它运行在整个RTSJ实现以及实时线程。优先级继承protocol-a知名实时调度algorithm6-must默认实现。该规范还提供了一种机制,您可以覆盖默认的系统范围策略,或控制用于特定监视器的策略,只要实现支持该策略。monitor控制策略的规范是可扩展的,因此未来的实现可以添加机制。第二种策略,优先级上限仿真(或最高存储),也为支持它的系统指定。6决定论符合实现必须提供一个固定的上限为应用程序代码所需的时间进入一个同步块解锁监控。共享和线程间的通信实现人员最有可能使用普通Java线程的组合,RTs,nhrt。RTSJ允许锁定不同线程之间types-even最有争议的情况下,在常规线程和nhrt。
如果NHRT试图锁定一个RT或常规线程已经锁定的对象,那么优先级继承就会正常。有一个问题:non-NHRT有其优先级提高不能执行垃圾回收器执行。因此,如果一个垃圾收集正在进行中,那么这个被提升的线程将被挂起,直到收集完成。这当然会导致NHRT因为收集而延迟。为了解决这个问题,RTSJ提供机制,允许nhrt通信(同步)的一种形式与RTs和普通Java线程,同时避免在nhrt garbage-collector-induced延迟。RTSJ提供队列类nhrt和普通Java线程之间的通信。图2显示了一个无等待写队列,这是单向从实时、非实时。nhrt通常使用写(实时)操作;常规线程通常使用读操作。写端阻塞(任何试图立即写信给一个完整的队列返回“false”)和同步(如果多个NHRT可以写,他们必须同步),所以从垃圾收集NHRT不会造成延误。读操作,另一方面,阻塞(它会等待,直到有数据队列)和同步(它允许多个读者)。当一个NHRT普通Java线程发送数据,它使用无等待队列操作,和常规的线程使用一个同步操作出列。一个读队列,它是单向的,从非实时到实时的,以相反的方式工作。因为写无等待,动力学是不相容的,数据可能会丢失。为了避免在分配内存元素时出现延迟,类构造函数静态地分配用于队列元素的所有内存,从而使队列具有有限的限制。如果常规线程没有以足够高的速率从队列中删除元素,那么队列可能会满。
全套毕业设计论文现成成品资料请咨询微信号:biyezuopin QQ:2922748026
返回首页
如转载请注明来源于www.biyezuopin.vip
|