由于WSNOS的特殊性,它的调度机制需要简单而实用。下面以TinyOS为例,介绍WSNOS的调度机制。
1.1 调度
TinyOS的调度模型为任务加事件的两级调度,调度的方式是任务不抢占事件要抢占,调度的算法是简单的FIFO,任务队列是功耗敏感的。调度模型有以下的特点:
a) 基本的任务单线程运行到结束,只分配单个任务栈,这对内存受限的系统很重要。
b) FIFO的任务调度策略是电源敏感的。当任务队列为空,处理器休眠,等待事件发生来触发调度。
c) 两级的调度结构可以实现优先执行少量同事件相关的处理,同时打断长时间运行的任务。
d) 基于事件的调度策略,只需少量空间就可获得并发性,并允许独立的组件共享单个执行上下文。同事件相关的任务集合可以很快被处理,不允许阻塞,具有高度并发性。
TinyOS只是搭建好了最基本的调度框架,只实现了软实时,而无法满足硬实时,这对嵌入式系统的可靠性会产生。同时,由于是单任务的内核,吞吐量和处理器利用率不高,因此有可能需要设计多任务系统。为保证系统的实时性,多采用基于优先级的可抢占式的任务调度策略。依赖于应用需求,出现了许多基于优先级多任务的调度算法的研究。把TinyOS扩展成多任务的调度,给TinyOS加入了多任务的调度功能,提高了系统的响应速度。[提出在TinyOS中实现基于时限(deadline)的优先级调度,有利于提高WSN系统的实时性。提出了一种任务优先级调度算法来相对提高过载节点的吞吐量以解决本地节点包过载的问题。
总之,调度决定了处理器的功耗,如TinyDB就是使用好的调度策略来降低功耗的。更为重要的是,各种调度算法也能更好地提高处理器的响应速度,从而提高系统的可靠性。各种基于TinyOS调度算法的扩展研究,各自独立地使得高可靠性和低功耗分别得到满足。
1.2 中断
在TinyOS中,代码运行方式为响应中断的异步处理或同步地调度任务。TinyOS的每一个应用代码里,约有41%-64%的中断代码,可见中断的优化处理非常重要。对于低功耗的处理而言,需要长时间休眠,可以通过减少中断的开销来降低唤醒处理器的功耗。目前通过禁用和打开中断来实现原子操作,这个操作非常的短暂(几个时钟周期--cycles)。然而,让中断关掉很长时间会延迟中断的处理,造成系统反应迟钝。TinyOS的原子操作能工作得很好是因为它阻止了阻塞的使用也限制了原子操作代码段的长度,而这一些条件的满足是通过nesC编译器来协助处理的。由于nesC编译器对TinyOS做静态的资源分析以及其调度模式决定了中断不允许嵌套。在多任务模式下,中断嵌套可以提高实时响应速度。
1. 3 时钟同步
TinyOS提供获取和设置当前系统时间的机制,同时,在WSN网络中提供分布式的时间同步。TinyOS是以通讯为中心的操作系统,因此更加注重各个节点的时间同步。如:传感器融合应用程序收集一组从不同地方读来的信息(如:较短距离位置需要建立暂时一致的数据);TDMA风格的介质访问协议需要精确的时间同步;电源敏感的通讯调度需要发送者和接收者在他们的无线信号开始时达成一致等。
加州大学洛杉矶分校(UCLA) 、Vanderbilt和加州大学伯克利分校(UC Berkeley) 分别用不同方法实现了时间同步。这3个实现都精确到子毫秒级,最初打算开发一个通用的、底层的时间同步组件,结果失败了。应用程序需要一套多样的时间同步,因此只能把时钟作为一种服务来灵活地提供给用户取舍使用。
某些情况允许逐渐的时间改变,但另一些则需要立即转换成正确的时间。当时间同步改变下层时钟时,会导致应用失败。某些系统,例如NTP(Network Time Protocol)通过缓慢调整时钟率同邻节点同步来规避这个问题。NTP方案很容易在像TinyOS那样对时间敏感的环境中出错,因为时间即使早触发几毫秒都会引起无线信号或传感器数据丢失。
目前TinyOS采用的方案是提供获取和设置当前系统时间的机制(TinyOS的通讯组件GenericComm使用hook函数为底层的通讯包打上时间戳,以实现精确的时间同步),同时靠应用来选择何时激活同步。例如:在tinydb应用中,当一个节点监听到来自于路由树中父节点的时间戳消息后会调整自己的时钟以使下一个通讯周期的开始时间跟父节点一样。它改变通讯间隔的睡眠周期持续时间而不是改变传感器的工作时间长度,因为减少工作周期会引起严重的服务问题,如数据获取失败。
J. Elson和D. Estrin给出了一种简单实用的同步策略。其基本思想是,节点以自己的时钟记录事件,随后用第三方广播的基准时间加以校正,精度依赖于对这段间隔时间的测量。这种同步机制应用在确定来自不同节点的监测事件的先后关系时有足够的精度。设计高精度的时钟同步机制是传感网络设计和应用中的一个技术难点。
也有一些应用更重视健壮性而不是最精确的时间同步。例如:TinyDB只要求时间同步到毫秒级,但需要快速设置时间。在TinyDB中,简单的,专用的抽象是种很自然的提供这种时间同步服务的方式,但是这种同步机制并不满足所有需要的通用的时间同步。另外,还可以采取Lamport分布式同步算法,并不全部靠时钟来同步。
1.4 任务通讯和同步
任务同步是在多任务的环境下存在的。因为多个任务彼此无关,并不知道有其它任务的存在,如果共享同一种资源就会存在资源竞争的问题。它主要解决原子操作和任务间相互合作的同步机制。
TinyOS中用nesC编译器检测共享变量有无冲突,并把检测到的冲突语句放入原子操作或任务中来避免冲突(因为TinyOS的任务是串行执行的,任务之间不能互相抢占)。TinyOS单任务的模型避免了其他任务同步的问题。如果需要,可以参照传统操作系统(例如μc/os)的方法,利用信号量来给多任务系统加上任务同步机制,使得提供的原子操作不是关掉所有的中断,从而使得系统的响应不会延迟。
在TinyOS中,由于是单任务的系统,不同的任务来自不同的网络节点,因此采用管道的任务通信方式,也就是网络系统的通信方式。管道是无结构的固定大小数据流,但可以建立消息邮箱和消息队列来满足结构数据的通信。
2 WSNOS内存管理
TinyOS的原始通讯使用缓冲区交换策略来进行内存管理。当网络包被收到,无线组件传送一个缓冲区给应用;应用返回一个独立的缓冲区给组件以备下一次接收。通讯栈中,管理缓冲区是很困难的。传统的OS把复杂的缓冲区管理推给了内核处理,以拷贝复杂的存储管理以及块接口为代价,提供一个简单的、无限制的用户模式。AM[ Active Messages ]通讯模型不提供拷贝而且只提供非常简单的存储管理。消息缓冲区数据结构是固定大小的。当TinyOS中的一个组件接收到一个消息,它必须释放一个缓冲区给无线栈。无线栈使用这个缓冲区来装下一个到达的消息。一般情况下,一个组件在缓冲区用完后会将其返回,但是如果这个组件希望保存这个缓冲区待以后用,会返回一个静态地本地分配缓冲区,而不是依靠网络栈提供缓冲区的单跳通信接口。尽管只有1个组件,任何时候只有一个进入给定缓冲区的指针,组件来回交换使用它们。
静态分配的内存有可预测性和可靠性高的优点,但缺乏灵活性。不是预估大了而造成浪费就是小了造成系统崩溃,为了充分利用内存,可以采用响应快的简单的slab动态内存管理。