冯韬+朱立才
摘 要: Contiki在物联网中的应用越来广泛,但用户对系统的认识却相对滞后。Contiki是一款适用于资源受限无线传感网操作系统,支持IPv6协议。在事件驱动的基础上,提供protothread线程模型,从而有效节省内存空间。文章介绍了Contiki的特点,结合main函数的执行流程深入剖析了Contiki的进程与事件以及事件与进程的关系。通过实例在Cooja下进行了仿真,并对结果进行了分析。
关键词: Contiki; 进程; 事件; protothread
中图分类号:TP316 文献标志码:A 文章编号:1006-8228(2016)12-01-04
Analysis of process and event of Contiki system
Feng Tao, Zhu Licai
(School of Information Science and Technology, Yancheng teacher's University, Yancheng, Jiangsu 224002, China)
Abstract: The application of Contiki system in the Internet of Things is more and more extensive, but the user's cognition of the system is relatively backward. Contiki is suitable for resource constrained wireless sensor networks, supports the IPv6 protocol, and on the basis of event driven, provides the protothreads threading model, which can effectively save memory space. In this paper, the characteristics of Contiki are introduced, combined with the execution process of the main function, the process and event of Contiki, and the relationship between them are analyzed. And an example is simulated with Cooja, the results are analyzed.
Key words: Contiki; process; event; protothreads
0 引言
无线传感器是无线传感网的核心部件,一般的无线传感器具有低能量、低处理能力、低存储能力和低数据传输速率的特点。因此,传统的操作系统不适用于无线传感网,需要研制适用的操作系统。目前应用于无线传感网的操作系统有TinyOS,μC/OS-Ⅱ,Contiki[1]等。Contiki是一款开源的、高度可移植的多任务操作系统,适用于需联网的嵌入式系统和无线传感器。该系统适用于资源受限的嵌入式单片机系统,典型情况下只需2K的RAM和40K的FLASH存储器,可移植到多种平台上。Contiki是基于事件驱动内核操作系统,在该内核上,应用程序可以在运行时动态加载。在事件驱动内核的基础上,提供了protothead线程模型,使多个线程共享一个任务栈,从而减少内存占用。具体来说,Contiki具有以下特点:事件驱动的多任务内核,多个任务可以共享一个栈;支持全IP网络,如IPv4,UDP,TCP和HTTP[2],支持低功耗有损网络协议,如6lowpan,RPL,CoAP[3]等;提供了能量耗费评估机制[2];支持运行时模块的动态链接和加载;提供内存块分配、托管内存分配器和标准的C内存分配器[2]三种内存分配方法;集成无线传感网络仿真工具Cooja[4]和MSP430[5];提供CFS文件系统[6]。
正因为Contiki系统具有的优越性,使其在学术界和工业界得到越来越广泛的重视。但Contiki的运行机制比较特殊,源码编写技巧性强,研究者往往无从入手。本文深入剖析Contiki的进程与事件,阐述两者之间的关系,并对之进行仿真,以便为Contiki的研究人员和开发人员提供一定的参考。
1 Contiki进程
Contiki使用事件驱动和Protothread两个主要的机制[1],前者能达到降低功耗的目的,后者可有效节省内存空间。
传统操作系统每个进程需要一个独立的栈,这个特点不适用于内存资源极度受限的无线传感设备。Contiki提供的Protothread机制解决了这个问题,通过保存被阻塞的进程行数来实现进程切换,而这在系统中只需两个字节即可实现。当该进程下一次被调用时,通过switch(_LINE_)进行跳转,恢复进程的执行[7]。通过这种机制,能有效节省内存空间。
1.1 Contiki编程模型
本文结合Contiki2.7中提供的例程Hello World给出Contiki的编程模型。
在该结构中包含进程名称(*name)、执行进程的宏(PT_THREAD)、用于保存程序被中断行数的结构体(pt)、程序状态(state)和进程优先级。
分别表示进程已退出,但还没有从进程链表中删除;进程已放于执行队列,还没有取得执行权;进程取得执行权并投入运行。
进程优先级needspoll,即当系统调用process_run()函数时,有所needspoll标志为1的进程投入运行,之后才会从事件队列取出下一个事件传递给相应的监听进程。
1.3 进程链表
Contiki将进程组织成一个链表结构,一个头指针process_list指向该表头,通过遍历链表处理进程。
2 Contiki事件
为了节省能耗,嵌入式系统将周围环境的变化看成一个个事件,事件到来,系统进程处理,否则,系统就处于休眠状态。
Contiki将所有事件存放于一个全局的静态数组中,数组采用环形结构。事件数目在系统运行之前就要指定(用户可以通过PROCESS_CONF_NUMEVENTS配置其大小),通过数组下标可以快速访问事件。系统还定义两个全局静态变量nevents和fevent,分别用于记录未处理事件总数及下一个待处理的位置。
因此对于Contiki系统而言,事件遵循先到先服务策略。
2.1 事件产生
Conitki有两种产生事件的方式,即同步方式和异步方式。同步事件通过process_post_synch函数产生,事件触发后直接处理(调用call_process函数)。而异步事件产生是由process_post产生,产生后放入事件队列等待处理。
2.2 事件调度
do_event函数用于处理事件。它首先取出该事件,由于采用环形数组存放待处理的事件,所以在计算未处理事件总数及下一个待处理事件的数组下标时,需用取余操作。然后判断事件是否为广播事件PROCESS_BROADCAST,由于处理广播事件可能需要更多的时间,为保证系统实时性,先运行高优先级的进程,然后再去处理事件(调用call_process函数)。如果事件是初始化事件PROCESS_EVENT_INIT(创建进程的时候会触发此事件),需要将进程状态设为PROCESS_STATE_RUNNING。
2.3 事件处理
call_process会调用thread函数处理事件。
2.4 事件的数据结构
struct event_data
{ process_event_t ev;
process_data_t data;
struct process *p;
};
typedef unsigned char process_event_t;
typedef void * process_data_t;
上述结构体含义为:标识产生的事件(ev)、给进程传输的数据(data)以及监听该事件的进程(p)。
2.5 事件的分类
Contiki系统的事件可分为三类:时钟事件、外部事件和内部事件。时钟事件可以看成是特殊的内部事件。
⑴ 系统事件
系统定义了10个事件,以0x80~0x8a标识。如:
⑵ 定时器事件
Contiki系统包括五种定时器:
timer和stimer:提供了最简单的时钟操作,即检查时钟周期是否已经结束。两种时钟最大的不同在于,tmier使用系统时钟的ticks,而stimer是使用的秒。
ctimer:活动时钟。当它过期时,调用一个函数。
etimer:活动时钟。当它过期时,发送一个事件。
rtimer:实时时钟。在某个确定的时间调用一个函数。
3 进程、事件和etimer之间的关系
3.1 事件与etimer关系
etimer_process执行时,会遍历整个etimer链表,检查etimer是否有到期的,如有到期的就把事件PROCESS_EVENT_TIMER加入到事件队列中,并将该etimer成员变量p指向PROCESS_NONE。PROCESS_NONE用于标识该etimer是否到期,函数etimer_expired会根据etimer的p是否指向PROCESS_NONE来判断该etimer是否到期。
3.2 进程与etimer关系
etimer是一种特殊事件。etimer与process并不是一一对应的关系,即一个etimer必定绑定一个process,但process不一定非得绑定etimer。
3.3 进程与事件关系
当有事件传递给进程时,就新建一个事件加入事件队列,并绑定该进程,所以一个进程可以对应于多个事件,而一个事件可以广播给所有进程,即该事件成员变量p指向空。当调用do_event函数时,将进程链表所有进程投入运行。
在Contiki中每一种硬件平台都对一个相应的main源程序,在该程序中含有main函数,嵌入式系统不断运行着main函数中的循环。本文以Contiki 2.7中的
main()函数的主要执行过程如下。
⑴ 硬件初始化:根据不同的硬件平台,对相关的硬件进行初始化,包括串口、网络等。
⑵ 时钟初始化:对系统时钟进行初始化,不同的平台所使用的时钟会有所不同。
⑶ 进程初始化:Process_init()函数主要是完成事件队列和进程链表初始化。
⑷ 启动系统进程:特别是与时钟相关的进程,完成系统的特定功能。
⑸ 启动用户指定自动运行的进程。
⑹ 进入事件处理的循环:遍历所有高优先级的进程并执行,然后转去处理事件队列的一个事件,将该事件与进程绑定。主要包括如下阶段。
创建进程:由宏PROCESS完成,主要包括两个方面,一是定义一个进程控制块,二是定义进程执行体的函数。
启动进程:由process_start()函数启动一个进程,如果进程不在链表中,将进程加入进程链表,并给该进程发一个初始化事件PROCESS_EVENT_ INIT,初始化进程的运行状态,将lc设为0。
进程退出:执行退出进行函数exit_process。先进行参数验证,确保进程在进程链表中并且不是PROCESS_STATE_NONE状态,向所有进程发一个同步事件PROCESS_EVENT_EXITED。
4 仿真与分析
为验证进程的交互过程,本实验设置了两个进程First和Second,同时使用了etime事件。在Cooja下的仿真结果如图1所示。
系统启动时,会进行一系列初始化工作,接着启动系统进程etimer_process,进而启动进程First和Second。当进程First执行到PROCESS_WAIT_EVENT
_UNTIL(ev==PROCESS_EVENT_TIMER),由于etimer还没到期,进程被挂起,转去执行Second进程,当执行到PROCESS_系统启动时,会进行一系列初始化工作,接着启动系统进程etimer_process,进而启动进程First和Second。当进程First执行到PROCESS_WAIT
_EVENT_UNTIL(ev==PROCESS_EVENT_TIMER),由于etimer还没到期,进程被挂起,转去执行Second进程,当执行到PROCESS_WAIT_EVENT_UNTIL(ev==event_data_ready)时,由第一个进程还没有执行post事件,该进程也被挂起。而后再转去执行系统进程etimer_process,直到检测到etimer到期,输出Etime expired,然后输出First process,并传递事件event_ data_ready给Second进程,重新初始化timer,再次执行First进程,由于etime没有到期,而post事件已执行,所以会转去执行Second进程,输出Second process。待执行到PROCESS_WAIT_EVENT_UNTIL(ev==event
_data_ready)又被挂起,再次执行系统进程etimer_process。如此反复在两个进程间进行调度[8]。
5 结束语
Contiki的事件驱动机制和Protothread线程模型非常适用于资源受限的无线传感器网络。本文在给出Contiki系统特点的基础上,详细分析了Contiki的事件结构,进程结构,以及进程和事件的关系,并通过main函数剖析了Contiki程序的执行流程,进一步阐述了事件和进程的关系。通过Cooja下对两个进程交互过程仿真,以及etime事件的应用,直观地反映三者之间的关系。接下来的工作将对系统源码作进一步分析,为系统的移植和使用Cooja进行协议的仿真打下基础。
参考文献(References):
[1] Dunkels A, Gronvall B, Voigt T.Contiki-a lightweight and
flexible operating system for tiny networked sensors.Local Computer Networks[C].Washington, USA: IEEE,2004:455-462
[2] Contiki community. Why Choose Contiki?http:// www.
contiki-os.org/index.html#why
[3] Kovatsch M, Duquennoy S, Dunkels A.A low-power coap
for contiki. Adhoc and Sensor Systems (MASS)[C].Valencia, Spanish: IEEE,2011:855-860
[4] Kugler P, Nordhus P, Eskofier B. Shimmer, Cooja and
Contiki: A new toolset for the simulation of on-node signal processing algorithms. Sensor Networks[C]. Cambridge, Massachusetts, USA: IEEE,2013:1-6
[5] Eriksson J, Osterlind F, Voigt T, Finne N, Raza S, Tsiftes
N, Dunkels A.Demo abstract: Accurate power profiling of sensornets with the cooja/mspsim simulator. Mobile Adhoc and Sensor Systems[C]. Macau, China: IEEE,2009:1060-1061
[6] Tsiftes N, Dunkels A, He Z, Voigt T.Enabling large-scale
storage in sensor networks with the coffee file system. Information Processing in Sensor Networks[C]. San Francisco, USA:IEEE,2009:349-360
[7] 苏铅坤.无线传感器网络文件系统与重编程技术研究[D].电
子科技大学,2013.
[8] Oikonomou G, Phillips I. Experiences from porting the
Contiki operating system to a popular hardware platform. Distributed Computing in Sensor Systems and Workshops[C]. Barcelona, Spanish: IEEE,2011:1-6