微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > VxWorks环境下基于Zinc的通信

VxWorks环境下基于Zinc的通信

时间:03-27 来源:互联网 点击:

1 引言

  VxWorks是美国Wind River Systems公司开发的一种嵌入式实时操作系统,它以高性能可剪裁的微内核以及友好的用户开发环境在嵌入式实时操作系统领域占有重要的地位。

  在很多实时应用场合(如嵌入式地理信息系统) ,需要在VxWorks环境下设计图形用户界面(GUI) 。VxWorks提供了两种开发图形用户界面的组件:WindML (Wind多媒体库)和Zinc。WindML为图形、图象和声音应用程序的开发提供了基本技术,并且提供了为定制设备开发标准化驱动程序的框架。 Zinc是以WindML为基础的, Zinc是为应用创建图形用户界面提供框架的可扩展的面向对象的类库。Zinc为实现复杂的图形用户界面提供了更多的支持。

  为了提高性能和简化源代码,大多数情况下在一个实时环境中的应用程序是以多任务的方式实现的, Zinc自身通常也是多任务的。一般不在外部任务里直接处理GUI ,而是在一个专用的GUI任务里执行所有的GUI处理。在多任务环境下,非GUI任务将需要在不同的时期和GUI任务通信, GUI也可能需要与外部任务通信。GUI任务与非GUI任务之间的通信方式将对整个实时系统的实时性、可靠性和稳定性产生重大的影响。因此, 深入研究VxWorks环境下Zinc所支持的GUI任务与非GUI任务之间的通信方式并确定在特定应用场合选择通信方式的原则是非常重要的。

2 GUI( Zinc)任务和外部任务之间的通信方法

  GUI任务和非GUI任务之间的通信大致可以分为两种:同步通信和异步通信。Zinc主要提供了如下几种通信机制供程序员选择使用:

  Zinc入口点
  共享内存
  OS消息队列
  派生设备
  a)Zinc入口点

  可以利用Zinc入口点实现GUI任务与非GUI任务之间的通信,主要有如下两种方法:

  与Zinc通信的基本入口点是ZafEventManager::Put()程序。利用该函数可以在Zinc事件队列中放置一个事件。这是一个异步方法,因此只能适用于可接受异步通信的场合。

  ZafApplication::BeginSynchronize() 和ZafApplication::EndSynchronize() 。这两个函数自身并不是通信程序,但能确保直接通信方式访问Zinc是安全的。直接通信通常由一个对象的Event()函数来实现,也可能采用其它的方式,比如数据对象更新。间接通信可以使用ZafEventManager::Unblock()函数来实现。使用一个派生设备或其它方法进行通信的时候, 使用该函数可以使正在等待事件的Zinc任务解除阻塞。

b)共享内存

  在VxWorks中很容易实现共享内存。为了安全地共享内存,最好让一个信号量和共享内存关联。这样可以避免任务之间出现资源冲突。

  使用共享内存的时候,通常不需要使用Zinc 提供的保证线程安全的入口点。但是当一个窗口对象的某个成员指向共享内存的时候是一个例外情况。例如,如果一个ZafButton的bitmapData 成员正指向共享内存,除非已经确保Zinc任务目前没有使用该共享内存,才能安全地更新该共享内存。可以使用ZafApplication:: BeginSynchronize() 和ZafApplication::EndSynchronize() 函数来保证在某一时刻该任务是唯一使用该共享内存的任务。

c)OS消息队列

  在VxWorks环境下使用Zinc的时候,有两种不同类型的消息队列可供选用:事件管理器消息队列和VxWorks操作系统提供的消息队列。

  可以通过ZafEventManager::Put()和ZafEventManager::Get()函数访问事件管理器消息队列。事件管理器队列只提供从非GUI任务到Zinc任务的通信,利用事件管理器队列进行从GUI任务到非GUI任务的通信是不实用的。

  VxWorks消息队列可以实现从GUI任务到非GUI任务的通信,也可以实现从非GUI任务到GUI任务的通信,但是不允许同时在两个方向上进行通信。

d)派生设备

  选用共享内存或消息队列作为通信方法时,Zinc需要与该通信方法进行交互,这可以通过派生设备实现。使用派生设备的目的是为了检查是否有来自另一个任务的通信。每当ZafEventManager::Get() 函数被调用,事件管理器轮询该设备,看看是否有新消息。这个派生设备仅仅需要检查共享内存或消息队列。如果有新信息可用,派生设备可以直接调用对象的 Event() 函数在队列上面放置一个新事件,也可以自己处理这个消息。

  派生设备还可用于实现从GUI任务到非GUI任务的通信。

  ZafEventManager::UnBlock()函数对这种通信方法是非常有用的。在正常的情况下,如果没有需要处理的事件, Zinc会阻塞自己。如果采用一个派生设备监听一个VxWorks消息队列,向该队列发送一个消息后解除事件管理器的阻塞可以更及时地轮询该派生设备。派生设备自身不会阻塞,也不会导致Zinc暂停。

3 选择通信方式的原则

  上述关于GUI任务的通信方法各有其优缺点。在选择通信方法的时候,应该以具体的应用场合为依据,一般应遵循如下的原则:

a) 应该尽可能选用简单的通信方式。

  在大多数情况下, Zinc入口点足够用。Zinc入口点是最简单的关于GUI任务的通信方式,因为它们不需要Zinc 任务内部的任何专门代码。可用的最简单入口点是ZafEventManager::Put()函数。然而,它有下列缺点:第一,它只允许从非GUI任务到 GUI任务的通信;第二,它是异步的;第三,因为要防止ZafEventManager::Get() 和ZafEventManager::Put()函数同时访问Zinc事件队列以对其进行保护, ZafEventManager::Put() 可能会阻塞。

  如果异步通信是可接受的,但是不能接受阻塞,可以采用下列两种方法:第一,使用 ZafEventManager::Put ( )函数,并且另外有一个可被阻塞的任务向Zinc队列中放置事件。这个任务可以监听一个OS消息队列,而原先产生消息的任务正是使用OS消息队列来发送消息; 第二,创建一个设备以监听OS消息队列,产生消息的任务发送一个消息给OS消息队列,然后由派生设备接收并解释。派生设备可以放置一个事件在Zinc队列中,或者自己处理这个事件。只是这两种方法都给应用程序增加了一点复杂性。

b) 如果需要进行同步通信,必须使用函数对ZafApplication::BeginSynchronize() 和ZafApplication::EndSynchronize() 。

  调用ZafApplication::BeginSynchronize()之后,可以保证对Zinc对象的任何访问是安全的。该方法很简单,且不需要在GUI任务中添加专门的代码。使用ZafApplication::BeginSynchronize() 的缺点是该函数会阻塞,使用该方法时必须采取预防措施。

c) 采用共享内存进行通信时必须创建保护和同步机制

  共享内存是从GUI任务到非GUI任务的两种通信方法之一,其优点是对数据的访问简单而直接。共享内存没有对数据访问进行保护的内在支持,所以必须创建一个对访问进行保护及同步的机制,并且访问共享内存的所有任务都应该使用该机制。采取这种方案的缺点是容易发生阻塞。

d) 在不能接受阻塞的应用场合,最好使用OS消息队列。

  OS消息队列是从GUI任务到非GUI任务和从非GUI任务到GUI任务进行通信的另一种方法。使用OS消息队列进行通信的时候,需要在GUI任务和非 GUI任务中编写访问消息队列的代码。在正确进行设置的情况下,消息队列不会引起阻塞的问题。创建消息队列时,必须保证消息队列有足够的消息容量或者建立处理消息队列溢出的机制。

4 Zinc的事件模型

  Zinc中的GUI任务与非GUI任务的多种通信方式都与Zinc的事件模型有关,因此在设计和实现GUI任务与非GUI任务之间的通信时,需要对Zinc的事件模型有深入的理解。Zinc具有一个事件驱动的体系结构。输入设备与应用程序之间的交互是通过事件完成的。由于VxWorks本身不是事件驱动的实时操作系统,在VxWorks运行平台中, Zinc主要从输入设备和应用任务获取事件。

  然后Zinc以标准的方式将这些事件打包,并且将它们路由给适当的对象以进行进一步的处理。在EGIS中, GSM通讯任务使用了自定义的事件与GUI任务进行异步通信。基于Zinc的EGIS事件模型如图1所示。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top