《无线传感网络》讲义(WirelessSensorNetwork)主讲人:杨博雄第三站:无线传感网络操作系统主要景点景点一:TinyOS操作系统景点二:Contiki操作系统景点三:MantisOS操作系统景点四:SOS操作系统景点五:Z-Stack协议栈景点一:TinyOS操作系统7.1TinyOS操作系统TinyOS是由美国加州大学伯克利分校设计和开发的一个开源的、BSD许可的、支持IEEE802.15.4和6loWPAN协议的适用于物联网以及无线传感网络特殊开发需要的微型操作系统。官方网址:最新版本是TinyOS2.1.2。学习网站:操作系统TinyOS与CrossBow(柯思博)联合推出的Mica、Telosb系列传感器节点等硬件平台珠联璧合而声名鹊起。TinyOS核心代码仅有400Bytes左右,能够突破传感器存储资源少的限制,让TinyOS很有效地运行在无线传感网络节点上,并执行相应的管理工作等。为满足无线传感网络开发的特殊要求,TinyOS中引入轻线程、主动消息、事件驱动和组件化编程等技术。TOSSIM(TinyOSsimulator)是TinyOS自带的一个仿真工具,可以支持大规模的网络仿真。7.1TinyOS操作系统7.1TinyOS主要特点组件化编程(Componented-Based)TinyOS提供一系列可重用的组件,一个应用程序可以通过连接配置文件(AWiringSpecification)将各种组件连接起来,以完成它所需要的功能。事件驱动模式(Event-Driven)TinyOS的应用程序都是基于事件驱动模式的,采用事件触发去唤醒传感器工作。事件相当于不同组件之间传递状态信息的信号。当事件对应的硬件中断发生时,系统能够快速地调用相关的事件处理程序。7.1TinyOS主要特点轻量级线程(lightweightthread)轻量级线程,即任务。任务之间是平等的,不能相互抢占,按先入先出队列(FirstInputFirstOutput,FIFO)进行调度。轻线程是针对节点并发操作可能比较频繁,且线程比较短的问题提出的。主动消息通信(ActiveMessage)每一个消息都维护一个应用层的处理程序。当节点收到消息后,就会把消息中的数据作为参数,传递给应用层的处理程序,由其完成消息数据的解析、计算处理或发送响应消息等工作。7.1.1TinyOS的框架结构TinyOS操作系统包括硬件层、软件层和上层应用。硬件层是对各种传感器、执行器、时钟、无线模块等硬件封装。这些硬件能够触发事件并把信息交由软件层处理,同时软件层会把高层应用发出命令给硬件层处理。如下图所示:7.1.2TinyOS的硬件平台抽象硬件抽象组件感知组件执行组件通信组件应用组件主组件(包括调度器)TinyOS提供了大多数传感网硬件平台和应用领域里都可用到的组件,例如定时器组件、传感器组件、消息收发组件、电源管理组件等,从而把用户和底层硬件隔离开来。在此基础上,用户只需开发针对特殊硬件和特殊应用需求的少量组件,大大提高了应用的开发效率。7.1.3TinyOS的调度机制事件(Events)和任务(Tasks)是TinyOS操作系统中最主要的两个触发源。这两个触发源容易出现并发冲突,这是TinyOS操作系统调度机制要解决的问题。为了解决这个问题,该操作系统内的调度器能够实现任务和事件的二级调度。TinyOS对于事件的调度是遵循抢占任务方式的机制,并且事件之间也可以相互抢占。但是TinyOS对于任务的调度则使用先进先出(FIFO)的机制,并且任务之间不能互相抢占。从调度器对这两者不同的调度机制可以看出,事件的优先级高于任务,同时由事件调用的命令优先级也高于任务。7.1.4nesC语言nesC:NetworkEmbeddedSystemC,是C语言的一个扩展,Tinyos操作系统本身也是由nesC编写完成的。nesC体现TinyOS的结构化概念和执行模型,实现结构和内容的分离,非常适合无线传感网络应用系统的开发。nesC有两个重要的概念:组件(component)和接口(interface)。(1)接口一个完整的nesC程序是由一系列组件构成的,这些组件彼此之间通过事先定义好的接口进行沟通,接口可以理解为两个组件之间进行交流的渠道,从而达到协调程序各部分间合作的目的。接口是一组相关函数的集合,它是双向的并且是组件间的唯一访问点。接口声明了两种函数:命令(command):接口的提供者必须实现它们事件(event):接口的使用者必须实现它们(1)接口interfaceReadval_t{asycommanderror_tread();asyeventvoidreadDone(error_tresult,val_tval);}接口内的函数只包含了函数的声明,但并不包含函数体。接口内的函数分两类:命令(command)和事件(event)。命令是接口具有的功能,事件是接口具有的通告事件发生的能力。(1)接口接口只有被某一个nesC组件实现(implementation)才具备真正的执行能力。我们把负责实现某一个接口的组件称为该接口的提供者(provider),而把需要使用该接口的组件称为该组件的使用者(user)。①一个接口可以连接多个同样的接口。②一个模块可以同时提供一组相同的接口,又称参数化接口,表明该模块可提供多份同类资源,能够同时分享给多个组件。③接口的提供者未必一定有组件使用,但接口的使用者一定要由组件提供。④同一个接口可以由不同的组件来实现,但是如果传感器平台不同,Read接口的提供者就未必相同。(2)组件一个nesc编写的程序由一个或多个组件构成或连接而成。一个组件由两部分组成:一个是规范说明,包含要用接口的名字;另一部分是它们的具体实现。组件分两种:Module组件(模块):实现某种逻辑功能;Configuration组件(配件):将各个组件连接起来成为一个整体。组件特征:组件内变量、函数可以自由访问,但组件之间不能访问和调用。(2)组件ComponentM1{provides{interfaceP1;interfaceP2;……}uses{interfaceU1;interfaceU2;……}}implementation{……//实现部分}组件的实现(implementation)作用域,对于模块来说该部分是程序功能的代码实现部分,它实现了所提供的接口中的命令和使用的接口中的事件;对于配件来说该部分用于将接口的使用组件和提供组件之间连接起来组成一个程序。组件(模块或配件)的规范(specification)作用域。组件根据功能需要可以声明所使用和提供的接口,也可以不提供(或)使用任何接口。component代表module或configuration组件标识符(identifier)P1:接口标识符(名字),模块M1必须实现它所提供接口的命令(command)。U1:接口标识符,模块M1必须实现它所使用的接口中事件(event)。(2)组件的模块模块主要用于描述组件的接口函数功能以及具体的实现过程,每个模块的具体执行都由4个相关部分组成:命令(command)函数、事件(event)函数、数据帧和一组执行线程。命令函数是可直接执行,也可调用底层模块的命令,但必须有返回值,表示命令是否完成。返回值有3种可能:成功、失败、分步执行。事件函数是由硬件事件触发执行的,底层模块的事件函数与硬件中断直接关联,包括外部事件、时钟事件、计数器事件。配置则是负责将各个模块通过特定的接口连接(wiring)起来,其本身并不负责实现任何特定的命令或者事件。(2)组件的配置模块配件moduleX{provides{interfaceA;......}uses{interfaceB;......}}implementation{command{......}......event{......}}configuartionX{providesinterfaceY;......}implementation{componentsA,B;A.Y-B.Y;.....}nesC语言编写的文件以“.nc”为后缀。每个*.nc文件实现一个组件功能。一个完整的应用程序一般有一个称为Main的组件作为程序的执行体(类似于C的main函数),Main组件调用其他的组件以实现程序的功能。如图所示:(3)nesC程序示例4.命令(command)command使用:moduleM2{usesinterfaceA1;}implementation{…intret=callA1.cmd1(0x11);…}调用command时一定要用call命令,否则编译会出错。5.事件(event)也是在接口中的一种函数,这种函数要求接口的提供者调用,而接口的使用者则会实现这种函数。形象的称为event,即为接口使用者所实现的事件处理函数。语法结构类C语言,只是在最前面增加event关键字。5.事件(event)event定义:interfaceA1{…eventvoidevent1(intarg1,intarg2);}可以拥有参数和返回值。5.事件(event)event实现:moduleM1{providesinterfaceA1;}implementation{…postA1.event1(0x1,0x2);/*发出对应的事件,实际上类同于调用事件处理函数*/…}接口的提供者在发出事件时,必须使用关键字post,否则编译会出错5.事件(event)event使用:moduleM2{usesinterfaceA1;}implementation{eventvoidA1.event1(intarg1,intarg2){…}}接口使用者必须实现event的具体内容,如同事件处理函数一样。组件、接口、命令和事件ComponentM1{provides{interfaceP1;interfaceP2;……}uses{interfaceU1;interfaceU2;……}}implementation{……//实现部分}组件的实现(implementation)作用域,对于模块来说该部分是程序功能的代码实现部分,它实现了所提供的接口中的命令和使用的接口中的事件;对于配件来说该部分用于将接口的使用组件和提供组件之间连接起来组成一个程序。组件(模块或配件)的规范(specification)作用域。组件根据功能需要可以声明所使用和提供的接口,也可以不提供(或)使用任何接口。component代表module或configuration组件标识符(identifier)P1:接口标识符(名字),模块M1必须实现它所提供接口的命令(command)。U1:接口标识符,模块M1必须实现它所使用的接口中事件(event)。7.1.4nesC语言nesC语言特点:1、结构和内容的分离:程序由组件构成,它们装配在一起(“配线”)构成完整程序。2、根据接口的设置说明组件功能。接口可以由组件提供或使用。被提供的接口表现它为使用者提供的功能,被使用的接口表现使用者完成它的作业所需要的功能。3、接口有双向性:它们描述一组接口供给者(指令)提供的函数和一组被接口的使用者(事件)实现的函数。4、组件通过接口彼此静态地相连。这增加运行时效率,而且允许更好的程序静态分析。1.接口一个完整的nesC程序是由一系列组件构成的,这些组件彼此之间通过事先定义好的接口进行沟通,接口可以理解为两个组件之间进行交流的渠道,从而达到协调程序各部分间合作的目的。nesC的接口有双向性:它们描述一个多功能的两组件(供给者和使用者)之间的交互渠道,即描述了两组件的调用关系。接口可以理解为函数原型的集合。1.接口如何定义接口:接口放在一个