第11章 nesC语言与TinyOS操作系统_第1页
第11章 nesC语言与TinyOS操作系统_第2页
第11章 nesC语言与TinyOS操作系统_第3页
第11章 nesC语言与TinyOS操作系统_第4页
第11章 nesC语言与TinyOS操作系统_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第11章nesC语言与TinyOS操作系统

提纲11.1nesC编程语言11.1.1nesC语言规范11.1.2模块及其组成11.1.3配件及其组成11.1.4基于nesC语言的应用程序11.1.5Blink实例11.1.6nesC语言程序运行模型11.1.7编程约定11.2TinyOS操作系统11.2.1传感网对操作系统的需求11.2.2TinyOS组件模型11.2.3TinyOS通信模型11.3本章小结前言TinyOS操作系统最初采用汇编语言和C语言编写加州大学伯克利分校的研究人员对C语言进行了扩展,提出了支持组件化编程的nesC语言。nesC编程语言把组件化/模块化的思想和基于事件驱动的执行模型结合了起来,并通过组织、命名和连接组件形成一个嵌入式网络系统,能很好地支持TinyOS的并发运行模式。TinyOS操作系统、组件库和服务程序都是采用nesC语言编写,通过用nesC语言编写TinyOS和基于TinyOS的应用程序,可以使应用开发更加方便并提高应用执行的可靠性。11.1nesC编程语言

nesC的设计体现了TinyOS的结构化概念和执行模型。TinyOS是特别为无线传感网节点设计的基于事件驱动型的操作系统,以适应传感器节点资源非常有限的特点。nesC语言在设计中的基本概念主要包括以下几点:(1)程序构造和组合机制相分离。整个程序由多个组件“连接(wired)“而成。组件定义了两个范围:接口定义的范围。实现定义的范围。组件可以以任务的形式存在,并具有内在并发性。线程控制可以通过组件的接口传递给组件本身。这些线程可能源于一个任务或一个硬件中断。11.1nesC编程语言--nesC语言基本概念(2)组件的行为规范由一组接口来定义。接口或者由组件提供,或者被组件使用。组件提供给用户的功能由它所提供的接口体现,而被组件使用的接口体现该组件完成其任务所需其他组件提供的功能。(3)接口具有双向性。一组接口供给提供的函数(即命令)和一组由接口的使用者实现的函数(即事件)。允许单一的接口能够表达组件之间复杂的交互作用,例如在某些事件中注册感兴趣的操作,而后当事件发生时回调这些操作。这一点至关重要,因为在TinyOS中,需较长运行时间的命令(例如发送包的命令)是非阻塞的,它们完成后会触发相关事件(例如发送完成的事件)。命令的调用都是自上向下的。例如从应用组件调用那些比较靠近硬件的组件,而事件则采取向上触发的方式。11.1nesC编程语言--nesC语言基本概念(4)组件通过接口彼此静态地相连。这种连接方式提高了程序运行效率,增强鲁莽性,而且允许更好的程序静态分析。(5)nesC的设计考虑到由编译器生成完整程序代码的需求。可以提供较好的代码重用和分析:nesC编译时(commpile-time)数据竞争监视器。(6)nesC的并发运行模型是作业一旦开始就持续至完成(run-to-completion)。不同中断源可以彼此打断作业。nesC编译器能够发现由中断源引起的潜在的数据竞争。11.1.1nesC语言规范——nesC语言术语

术语说明组件规范(specificationofcomponent)组件定义的接口名称、行为实现和使用范围,组件规范包含一系列规范元素规范元素(specificationofelements)是组件规范的组成元素,包括接口实例、命令和事件等。它可由组件提供(provided),也可以被组件使用(used)范围(extent)一个规范元素的生命周期。mesC采用标准C语言定义的生命周期:识别符、函数以及块命令(command)事件(event)组件定义中的一个函数,是一个规范元素,可位于一个组件接口实例中。当作规范元素使用时,命令和事件有角色(提供者,使用者)并且可以有接口参数。当有接口实例时,要区分没有接口参数的简单命令(事件)和有接口参数的参数化命令(事件)组件(component)nesC程序的基本单元。组件有名字而且分为两种:模块(module)和配件(configuration)。一个组件包括定义和实现两部分绑定/连接(wiring)配件定义的组件规范元素之间的联系模块(module)具体描述实现逻辑功能的组件11.1.1nesC语言规范——nesC语言术语

术语说明终点/端点(endpoint)组件的连接语句中的一个特定规范元素。一个参数化endpoint是对应一个参数化规范元素的没有参数值的endpoint内部的(internal)规范元素在一个配件C中,描述在配件C的组件列表中的一个组件的规范元素外部的(external)规范元素在一个配件C中,描述在配件C的定义中的一个规范元素。参见内部的规范元素扇入(fan-in)命令或事件描述由组件提供的命令/事件,此命令/事件可在多个地方被调用/触发扇出(fan-out)命令或事件描述被组件使用的命令/事件,此命令/事件被调用时,会进一步调用其他相关组件中接口的相关命令/事件函数,且结果会通过组合函数进行组合组合函数(combiningfunction)对扇出命令/事件调用的多个结果的组合函数。一个组合函数可以用来组合(进行某种逻辑操作)对这些被使用命令或事件调用的结果接口(interface)是一系列有名函数声明的集合。一般使用接口来指向(referto)一个接口类型或接口实例接口实例组件定义中一个特定接口类型的实例。接口实例由实例名、角色(提供者或使用者)和实例类型以及可选的接口参数构成。没有实例参数的接口是一个简单接口实例;有实例参数的接口是一个参数化接口实例11.1.1nesC语言规范——nesC语言术语

术语说明接口参数接口参数包含一个接口参数名而且必须是整型(integraltype)的。参数化接口实例的每个不同的参数值列表都有(概念上)一个不同的简单接口实例接口类型接口类型定义了提供者和使用者组件之间的交互。此接口类型定义有一系列命令和事件的形式。每个接口类型都有不同的名字接口的双向性一个接口的提供者(provider)组件实惠接口的命令;一个接口的使用者(user)组件实现接口的事件中间函数一个代表组件命令和事件行为的伪函数名字空间(nameSpace)nesC有标准那样的全局、函数参数和块范围。nesC还针对组件和接口类型,定义了组件和接口(componentandinterface)类型名字空间范围(scope)nesC有像标准C那样的全局、函数参数和块范围。nesC中的组件规定了规范和实现(specificationandimplementation)范围,每个接口都有自己的接口类型(pre-interface-type)范围11.1.1nesC语言规范——nesC语言术语

术语说明任务TinyOS中的可调度执行实体,类似于操作系统中的线程被使用者/提供者(provider)使用者(user)组件使用接口的一种描述。接口实例的使用者必须实现接口中的事件。接口实例的提供者必须实现接口中的命令组件提供的命令组件通过procides关键字提供给其他组件使用的接口命令组件使用的命令组件通过uses关键字声明其要使用的是由其他组件提供的接口命令组件使用的事件组件通过uses关键字声明的且需要在本组件中实现的事件编译错误(compile-timeerror)nesC编译器在编译时必须报告的错误配件中的概念模块中的概念1.接口接口是一系列声明的有名函数集合,接口是连接不同组件的纽带。接口是双向的,这种接口实际上是提供者(provider)和使用者(user)组件间的一个多功能交互通道。接口的提供者实现了接口的一组功能函数,称为命令(command);使用者需要实现一组功能函数,称为事件(event)。命令的调用都是向下的,即由应用组件调用那些与硬件结合紧密的组件,但是事件触发却正好相反。例如,组件A使用了由定时器组件B提供的定时器接口,组件A调用定时器接口里开启定时器的命令,该命令函数具体内容由组件B负责编写,而组件A负责编写定时器触发事件的函数内容。接口由接口类型定义,其语法如下所示:nesC-file:includes-listoptinterface//包含列表

…Interface:Interfaceidentifier{declaration-list}//

接口类型标识符的声明

Storage-class-specifier:alsooneofcommandeventasync//命令或事件的存储类型

2.组件组件有两种:模块(module)和配件(configuration)。模块负责提供一个或多个接口的实现;而配件负责把其他组件装配起来,把某组件的使用接口绑定到提供该接口的组件上。一个nesC组件可以是模块(module),也可以是配件(configuration)。组件的语法定义如下:nesC-file:includes-listoptmoduleincludes-listoptconfiguration…module:moduleidentifierspecificationmodule-implementationconfiguration:configurationidentifierspecificationconfiguration-implementation2.组件组件规范的语法定义如下:specification:{uses-provides-list}uses-provides-listuses-provides-listuses-providesuses-provides-list:usesspecification-element-listprovidesspecification-element-listspecification-element-listspecification-element{specification-elements}specification-elements:specification-elementspecification-elementsspecification-element2.组件一个组件规范中可以包含多个uses和provides语句。多个被使用(used)或被提供(provided)的规范元素可以通过包含在“{”和“}”符号中而组合在一起。例如,下面程序中两种定义是等价的:moduleA1{useslinterfaceX;usesinterfaceY;}moduleA1{uses{interfaceX;interfaceY;}}11.1.2模块及其组成

模块是主要用C语言实现的组件规范,它实际上是组件的逻辑功能实体,主要包括命令、事件、任务等的具体实现。模块的定义如下所示:module:moduleidentifierspecificationmodule-implementationmodule-implementation:implementation{translation-unit}这里的编译基本单位(translation-unit)是一系列的C语言声明和定义。模块中编译基本单位的顶层声明属于模块的组件实现范围。这些声明可以是:任何标准C语言的声明或定义;任务的声明或定义;命令或事件的实现。1.模块实现说明编译基本单位必须实现模块接口声明的全部命令和模块使用接口声明的所有事件。一个模块能调用它的任一命令和任一事件的信号,这些命令和事件的实现由如下的C语言语法扩展指定:storage-class-specifier:alsooneofcommandeventasyncdeclaration-specifiers:alsodefaultdeclaration-specifiersdirect-declarator:alsoidentifier.identifierdirect-declaratorinterface-parameters(parameter-type-list)2.调用命令和事件信号对C语言语法的下列扩展用于调用事件和向命令发出信号:postfix-expression:postfix-expression[argument-expression-list]call-kindopt

primary(argument-expression-listopt)…call-kind:oneofcallsignalpost一个简单的命令a可以使用calla(…)来调用,而一个简单的事件可使用signala(…)来触发。例如,在一个模块中使用SendMsg类型的接口Send:callSend.send(1,sizeof(Message),&msg1)。参数命令a有n个接口参数,类型为T1,……Tn由接口参数表达式e1,……en调用如下:calla[e1,……,en](…)。相应的可以用signala[e1,……,en](…)来触发事件。接口参数表达式ei必须符合类型Ti,实际的接口参数值是ei影射到Ti。3.任务任务是一个独立的控制实体,由返回类型为void且无参数的函数定义。一个任务可以预先声明,例如:taskvoidmyTask();任务通过前缀post来提交,例如:postmyTask()。提交操作将任务挂入任务队列,并立即返回;如果任务提交成功则返回1,否则返回0。Post表达式的类型是unsignedchar。相关定义如下:storage-class-specifier:alsooneoftaskcall-kind:alsooneofpost4.原子原子(atomic)可以用如下语句描述:atomic-stmt:atomicstatement原子通常是运行的最小单位,其主要目的是确保其运行时,没有其他运算同时发生。它一般用于更新并发性的互斥变量等。下面为原子的一个简单例子:boolbusy;//全局voidf(){

boolavailable;atomic{available=!busy;busy=TRUE;}if(available)do_something;atomicbusy=FALSE;}11.1.3配件及其组成

配件通过连接一系列其他组件来实现一个组件规范,它的功能主要是实现组件间的相互访问方式。配件的语法定义如下:configuration:configurationidentifierspecificationconfiguration-implementationconfiguration-implementation:implementation{component-listconnection-list}组件列表(component-list)用来建立这一个配件的组件,连接列表(connection-list)定义了这些组件是怎样互相连接以及如何与配件的规范连接在一起。这里把配件规范(specification)中的规范元素称为处部(external)规范元素,而把在配件实现(implementation)中的规范元素称为内部(internal)规范元素。1.包含的组件组件列表定义了用来实现配件的组件。这些组件可以在配件中重命名,这就可以解决与配件规范元素的名字冲突的问题或简化程序编写。为组件所选名字属于组件实现范围。组件列表的语法定义如下:component-list:componentscomponent-listcomponentscomponents:componentscomponent-line;component-line:renamed-identifiercomponent-line,renamed-identifierrenamed-identifier:identifieridentifierasidentifier如果两个组件采用as给出相同的名字,则会发生编译错误(例如,componentsX,YasX)。一个组件始终只有一个实例。如果组件K被用于两个不同的配件,或者在同一个配件中被使用两次,在程序中仍然只有K(及它的变量)的唯一实例。2.连接/绑定绑定(wiring)用于把定义的元素(接口、命令或事件等)联系在一起,以完成相互之间的调用。本节将定义绑定的语法和编译时的规则。后面会详细说明程序绑定声明是如何指出在每个调用和信号表达中哪个函数被调用。绑定的语法定义如下:connection-list:connectionconnection-listconnectionconnection:endpoint=endpointendpoint->endpointendpoint<-endpointendpointidentifier-pathidentifier-path[argument-expression-list]identifier-path:identifieridentifier-path,identifier3.隐式绑定隐式绑定可以写成K1<-K2.X或K1.Y<-K2(“=”和“->”是等价的)。该绑定形式通过规范元素K1来引用规范元素Y,因此K1.Y<-K2.X形成一个合法绑定。nesC会遍历K1的规范元素,寻找是否有与X对应的规范元素Y,如果有,则建立一个连接;否则就会出现编译错误。例如:moduleM1{procidesinterfaceStdControl;providescommandvoidh();}moduleM2{usesinterfaceStdControlasSC;}configurationC{providescommandvoidh();}implementation{componentsM1,M2;h2=M1,h;M2.SC->M1;}4.无参数化绑定的语义5.参数化函数绑定的语义11.1.4基于nesC语言的应用程序

1.应用程序总体框架2.应用程序开发步骤在了解nesC程序总体框架的基础上,可以开始应用程序的开发,其一般步骤如下:(1)在/opt/tinyos-2.x/apps目录下建立一个文件夹,通常以应用的名字命名。该文件夹通常包含以下4个文件:定制运行环境的makefile文件、头文件、顶层配件和核心处理模块。(2)定义头文件。与一般的程序开发类似,在头文件中定义一些数据结构,但头文件不是必需的。(3)编写顶层配件,包括3部分内容:接口的提供和使用的情况、使用的组件列表以及组件间的接口连接关系,这些都取决于应用程序的业务功能。(4)编写核心处理模块,包括两部分内容:接口的提供、使用的情况以及具体的实现代码。如果系统组件能满足应用需求,那么就不需要定义其他组件;否则,还要自定义组件以实现某些功能。这些自定义组件可放在系统组件库里,也可放在当前应用程序的目录里。3.应用程序的命名环境一个nesC语言编写的应用程序通常包括3个组成部分:基于C语言的声明和定义,接口文件以及组件文件。nesC应用程序的命名环境组织如下:最外层的全局命名范围(gobalscope),包含3个名字空间:C语言变量名字空间;C语言标签(tag)名字空间;用于组件和接口名称的名字空间。基于C语言的声明和定义有可能引入全局命名范围内的内嵌命名域。例如,函数声明和定义,函数内部代码段等。每个组件引入两个新的命名范围:包含组件规范元素的变量名字空间,内嵌在全局命名范围;变量和标签名字空间,内嵌在组件规范范围内的实现范围内。对于配件而言,实现范围的变量名字空间包含此配件所引用的组件的名字。对于模块,实现范围包含任务、构成模块体的C语言的声明和定义,这3部分构成了模块的主体。而这些定义又有可能引进在实现范围内的它们自身的嵌套范围,如函数体,代码块等。这种范围嵌套结构使得模块中的代码可以访问全局命名范围中的C声明和定义,但是不能访问其他组件中的任何声明或定义。4.应用程序的编译过程Ncc编译器可以将nesC语言程序编译成可执行文件。Ncc是在gcc编译器的基础上修改和扩充而来的。Ncc首先将nesC程序预编译为C程序,然后用交叉编译器将C程序编译成为可执行文件。在编译nesC程序时,具体操作步骤如下:(1)装载C文件X。在装载X时,先定位C文件,然后进行预处理,例如展开宏定义和包含的头文件X.h。C宏定义(由#define和#undef)的改变会影响到后面所有文件的预处理。来自被预处理的文件X.h的C声明和定义会进入C全局命名范围,因此对所有后来的C文件加工,对接口类型和组件都是有影响的。(2)装载顶层配件K。如果K已经被装载,就不用再做什么。否则,就需要定位并装入预处理文件X.nc(即组件K的文件)。对C宏定义(由#define和#undef)的变化被忽略。使用下面的语法分析预处理文件:nesC-file:includes-listoptinterfaceincludes-listoptmoduleincludes-listoptconfigurationincludes-list:includesincludes-listoptincludesincludes:includesidentifier-list;(3)装载顶层配件指定的所有接口类型。先定位接口,然后装入该接口包含的头文件。如果接口类型Ⅰ已经被装载,就不用再做什么;否则,就需要定位并装入接口的预处理文件X.nc(即接口Ⅰ的文件)。对C宏定义(由define和#undef)的变化被忽略。预处理文件同上面的nesC文件一样被分析处理。如果X.nc没有定义接口Ⅰ,将报告编译错误;否则,包含列表中指定的所有C文件都将被装载。接着,处理接口Ⅰ的定义。作为组件或接口包含C文件的例子,接口类型Bar可能包含用于定义Bar接口中变量类型的C文件BarTypes.h:Bar.nc:includesBarTypes;interfaceBar{commandresult_t

bar(BarTypearg1);}BarTyes.h:Typedef

struct{Intx;Doubley;}BarType;(4)装载顶层配件指定的所有组件。先定位组件,然后递归装入该组件使用的其他组件和相关文件。在将nesC语言程序预编译为C语言程序时,ncc下面的规则,将nesC语言程序中的标识符转化为C语言程序中的标识符:①如果C文件包含的标识符与nesC的关键字相同(因为nesC语言中的关键字在C文件中是非保留字,有可能出现相同标识符),那么在该标识符前加上_nesc_keyword前缀;否则,标识符保持不变。例如,C文件定义了名为module的变量,预编译后该变量的标识符被转化为_nesc_keyword_module。②组件C中的变量V被转化为C$V。③组件C中的函数F被转化为C$F。④组件C中的命令和事件A被转化为C$A。⑤组件C中的接口Ⅰ中的命令或事件A被转化为C$Ⅰ$A。5.应用程序下载到节点TinyOS系统支持多种硬件平台,每个硬件平台对应的文件保存在tos/platform目录中。在应用程序所在的目录中输入“make[platform]”命令,就能编译出运行在该平台的可执行代码。make命令调用ncc执行编译任务。Ncc提供了一些选项,常用的选项如下:-target=X//指定硬件平台-tosdir=dir//指定TinyOS目录-fnesC-file=file//指定存放预编译生成的C代码文件通过下载工具把机器码main.srec下载到传感器节点上,这里是通过uisp下载的,可以分3步进行:(1)擦除节点Flash中存放的原始代码;(2)把main.srec下载到节点的Flash中;(3)验证写入程序和原始文件是否一致。11.1.7编程约定

对于编程者来说,编程约定之所以非常重要,主要有以下5个原因:(1)一个软件生命周期的80%是用于软件维护的。(2)几乎很少有软件是始终由其最初编写者来维护的。(3)编程规范可以提高软件的可读性,使得阅读者能够更快速、透彻地理解陌生代码。(4)避免因冲突问题而导致无法编译或者编译错误。TinyOS系统中最需要留意的冲突是接口和组件的名字冲突。(5)良好的命名习惯可以帮助阅读者根据名字来识别该代码的组别,以及定义在哪一个软件包(package)中。所以编程者必须记住,编写合理的代码,可以有效减少阅读代码的时间,否则需要阅读代码的时间可能远多于编写的时间。在编程过程中即使偏离了下文的编程建议或要求,也要按照自己的编程习惯在所有代码中保持一致的约定。如果添加了新的约定,则应当在自述文件中注明。1.通用约定

编程过程中,还有一些通用的约定:(1)不要使用不常见的缩写。例如,不要为“justbecause”采用只取首字母的缩写。(2)缩写的首字母应当大写,例如应写成Adc而不是ADC。如果是两个单词的缩写,应当使每个单词的首字母大写,例如用AM表示主动消息(activemessage)。(3)如果需要缩写一个单词,请保持上下文的一致性,且最好与普遍认可的缩写一致。(4)所有代码都应当有说明文档。最好每一行命令、事件以及函数都有注释。最低限度是给接口、组件、类(class)或者文件编写一段说明。(5)如果您编写了一个代码文件,应当在文档说明的顶部加入@author标签。2.软件包软件包是所有相关源文件的集合,且不管这些文件是采用哪种编程语言来进行编程的。软件包在逻辑意义上是一个分组,但有可能并不是保存在同一个文件夹内。TinyOS系统中的软件包通常是一个包含零个或者多个子目录的目录。nesC语言和C语言都没有对软件包提供支持,所以在不同软件包中的接口和组件就有可能发生名字冲突。为了尽可能地减小这种冲突发生的几率,建议对相关文件采用前缀标识(这是惯用的做法)。此外,在一个软件包中,建议区分公共组件(可以被外部软件包调用)和私有组件(只能在软件包内部使用)。不过,这个区分在nesC中不是强制必须的。下面是关于软件包目录结构的一些说明:(1)每个软件包都应当有自己的目录,并且如果有必要可以下设多个子目录。(2)软件包的目录名应当和软件包的前缀相匹配,且要采用小写形式。(3)除系统内核外其他的软件包没有必要将组件和接口分隔开。毕竟,内核软件包有必要且应当允许组件可以适当的重载。(4)每一个目录都应该有一个自述文件来说明其用途。3.语法约定11.2TinyOS操作系统

11.2.1传感网对操作系统的需求11.2.1传感网对操作系统的需求

由于传感网的特殊性,需要操作系统能够高效地使用传感器节点的有限内存、低速低功耗的处理器、传感器、低速通信设备、有限的电源,且能够对各种特定应用提供最大支持。在面向传感网操作系统支持下,多个应用可以并发地使用系统资源。TinyOS操作系统有轻量级线程(lightweightthread)技术、主动消息(activemessage)通信技术、事件驱动(eventdriven)模式、组件化编程(component-basedprogramming)等。上述技术有助于提高传感网的性能,发挥硬件的特点,降低其功耗,并且简化了应用的开发。单个传感器节点的硬件资源有限,如果采用传统的进程调度方式,首先硬件就无法提供足够的支持;其次由于传感器节点的并发操作可能比较频繁,而且并发执行流程又很短,这也使得传统的进程/线程调度无法适应。11.2.1传感网对操作系统的需求

采用简单的轻量级线程技术和两层调度(two-levelscheduling)方式,可有效使用传感器节点的有限资源。这种模式下,一般的轻量级线程(task,即TinyOS中的任务)按照FIFO方式进行调度,轻量级线程之间不允许抢占;而硬件处理线程(在TinyOS中,称为硬件处理器),即中断处理线程可以打断用户的轻量级线程和低优先级的中断处理线程,对硬件中断进行快速响应。在通信协议方面,由于无线传感器节点CPU和能量资源有限,导致通信的并行度很高,所以采用传统的通信协议无法适应这样的环境。TinyOS的通信层采用主动消息通信协议。是一个基于事件驱动的深度嵌入式操作系统,所以TinyOS中的系统模块可快速响应基于主动消息协议的通信层传来的通信事件,有效地提高CPU的使用率。主动消息通信与二级调度策略的结合还有助于省电操作。TinyOS的事件驱动机制迫使应用程序在做完通信工作后,隐式地声明工作完成。TinyOS的调度下,所有与通信事件相关联的任务在事件产生时可以迅速进行处理。在处理完毕且没有其他事件的情况下,CPU将进入睡眠状态,等待下一个事件激活CPU。11.2.2TinyOS组件模型TinyOS还包含了经过特殊设计的组件模型,其目标是高效率的模块化和易于构造组件型应用软件。组件模型允许应用程序开发人员方便快捷地将独立组件组合到各层配件文件中,并在面向应用程序的顶层配件文件中完成应用的整体装配。nesC作为一种C语言的组件化扩展,可表达组件以及组件之间的事件/命令接口。在TinyOS中,每个模块由一组命令和事件组成,这些命令和事件成为该模块的接口。TinyOS的组件有四个相互关联的部分:①一组命令处理程序句柄;②一组事件处理程序句柄;③—个经过封装的私有数据帧;④一组简单的任务。11.2.2TinyOS组件模型图11-4所示为一个支持多跳无线通信的组件集合与这些组件之间的关系。上层组件对下层组件发命令,下层组件向上层组件发信号通知事件的发生,最底层的组件直接和硬件打交道。11.2.3TinyOS通信模型

1.主动消息概述主动消息模式是一个面向消息通信(message-basedcommunication)的高性能通信模式。早期一般应用于并行和分布式计算系统中,在主动消息通信方式中,每个消息都维护一个应用层(application-level)的处理器(handler),即处理子程序。当目标节点收到这个消息后,就会把消息中的数据作为参数,并传递给应用层的处理器进行处理。应用层的处理器一般完成消息数据的解包操作、计算处理或发送响应消息等工作。在这种情况下,网络就像是一条包含最小消息缓冲区的流水线,消除了一般通信协议中经常碰到的缓冲区处理方面的困难情况。为了避免网络拥塞,还需要消息处理器能够实现异步执行机制。尽管主动消息起源于并行和分布式计算领域,但其基本思想适合无线传感网的需求。主动消息的轻量级体系结构在设计上同时考虑了通信框架的可扩展性和有效性。主动消息不但可以让应用程序开发者避免使用忙等(busy-waiting)方式等待消息数据的到来,而且可以在通信与计算之间形成重叠,极大地提高CPU的使用效率,并减少传感器节点的能耗。5.通信接口和组件TinyOS系统提供了很多与底层通信相关的接口,并提供了实现这些接口的组件。所有的接口和组件使用一个共同的消息缓存区,称为message_t,一种nesC的结构体(类似于C语言的结构体struct)。message_t代替了TinyOS1.x里的TOS_Msg。与TinyOS1.x不同的是,message_t的成员是不透明的,即不能直接访问。更确切地说,message_t是一个抽象的数据类型,它的成员必须通过accessor函数和mutator函数来读写。(1)基本通信接口通信相关的接口和组件使用message_t作为底层的数据结构。通信接口的定义文件都位于tos/interfaces,下面介绍几个常用的通信接口:1)Packet接口:提供对message_t抽象数据类型的基本访问,其命令有:①voidclear(message_t*msg):清空消息缓存区中的内容。②void*getPayload(message_t*msg,uint8_tlen):返回消息有效载荷区的指针。③uint8_tpayloadLength(message_t*msg)-返回有效载荷区的长度。④uint8_tmaxPayloadLength():返回有效载荷区的最大长度。⑤voidsetPayloadLength(message_t*msg,uint8__tlen):设定有效载荷区的长度。2)Send接口:面向任意地址的消息发送接口,其命令和事件有:①error_t

send(message_t*msg,uint8_tlen):发送消息。②error_t

cancel(message_t*msg):取消消息的发送。③void*getPayload(message_t*msg,uint8_tlen):返回消息有效载荷区的指针。④uint8_tmaxPayloadLengt():返回有效载荷区的最大长度。.⑤voidsendDone(message_t*msg,error_terror):指示消息发送结果的事件。3)Receive接口:最基本的消息接收接口,提供了接收到消息时触发的事件函数:message_t*receive(message_t*msg,void*payload,uint8_tlen):返回刚接收到消息。4)PacketAcknowledgements接口:提供一种信息包确认的机制。5)RadioTimeStamping接口:为无线电的发射和接收提供时间标记信息。(2)主动消息接口考虑到一个应用程序里通常有多个服务需要使用同一个无线通信,TinyOS采用主动消息层(ActiveMessage,AM)来实现无线通信的多渠道访问机制。AM信息包也包含了目标地址域,把AM地址存储在特定节点的信息包中。1)AMPacket接口:类似Packet接口,提供对messaget抽象数据类型的AM访问。这个接口提供的命令

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论