以下有一些在使用protothreads(或Contiki processes)编程时需要特别注意的事项:
·局部变量未被保护: 当进程调用一个阻塞宏,实际是当前进程函数返回了,让内核调用其他的进程。当某个事件被投递,内核将调用相同的进程函数,函数将跳转至它之前返回的位置。 因此如果进程的局部变量(如果没有被声明为静态(static))在阻塞前被赋值,阻塞后继续执行,将不能保证仍为相同的值。一个好的方式是在进程函数中 使用静态(static)变量。
·不要使用switches:protothreads使用local continuations在返回后找回函数状态时,使用了switch语句。只有case语句放在if或while的语句块中,才不会和另一个switch语句混淆。因此,最好就是不要在进程函数中使用switch函数。
uIP TCP/IP stack
Contiki包括了一个轻量级的TCP/IP协议栈叫做uIP。它实现了RFC-定义的IPv4,IPv6,TCP和UDP(后两个兼容IPv4和IPv6)。uIP很高效,只实现了协议要求的特性。例如整个协议栈只有一个buffer,用于接收和发送数据报。
Application API
这里有两种方法使用uIP协议栈写程序:
·raw API:uIP raw API很适合实现一个简单的应用,例如一个简单的’echo’ server可以监听一些TCP端口并且将它收到的每个数据发送回去。然而当实现一个全功能的程序时编码变得越来越复杂,或者当多个程序需要共同使用时。甚至TCP连接状态机都有些烦人。
·protosocket API:protosocket library利用 protothread library,提供一个更灵活的方式编写TCP/IP程序。这个库提供了一个类似于标准BSD sockets的接口,并允许在一个进程中编写程序。
Lower Layers
拥有一个有效的TCP/IP协议栈并且某些程序可以运行在其上当然很好,但是还不够。uIP协议栈要求一个更低的层(根据OSI模型)为了和peers通讯。我们将讨论两种类型的peers。
·节点(nodes):节点间通信是由无线连接实现的。uIP协议栈需要能够发送和接受数据包。取决于uIP版本,Contiki遵循不同的方法:
·当使用IPv6,Contiki将遵循route-over配置。因此,uIP6使用一个被称为sicslowmac的简单MAC层。除了头部压缩由6loWPAN模型提供,它仅通过射频转发数据包。
· 然而,对于IPv4,Contiki选用mesh-under配置。这由Rime通讯协议栈完成。Rime提供mesh routing和路由发现,因此uIP使用它来转发网络上的数据包。从IP point的角度来看,所有的传感器网络节点组成了一个本地子网,虽然multiple radio hops可能被要求。
·网关(gateways):与WSN以外的网络通信,必须通过网关。网关连接WSN和另一个网络。一般接入的是PC,也可以是其他嵌入式系统。PC和mote是串口线连接的。IP报文通过SLIP协议在两者之间发送。在计算机端,必须运行一个程序作为串口线和网络接口的接口。根据uIP协议栈版本,节点的作用不同。
· 使用uIPv6时,有一个节点将被装载一个非常简单的程序,转发从射频收到的所有数据包至串口线,或者反向发送,它不做任何的地址比对,没有IP协议栈运 行在它上面,除了头部压缩/解压机制(6loWPAN)。这个节点被PC端仅视为一个以太网接口,由PC完成所有工作。
·使用uIPv4时则完全不同,节点作为网关连接至PC,有完整的IP协议栈在节点上运行。每当它收到数据包要发送,节点将检查报文的IP地址:如果它属于WSN子网范围,它将使用射频发送,否则它将使用串口线发送至PC。由PC运行一个程序来创建IP层网络接口。
Rime stack
Rime协议栈提供一种递阶型无线网络协议,从简单的匿名广播到mesh网络路由。一个复杂的协议(比如multihop mesh routing)实现会被分解成若干部分,复杂的模块利用相对简单的模块来组成。
以下是对Rime不同模块的简述:
·abc:匿名广播,它仅通过射频驱动发送数据包和接收所有的数据包,并将他们送至上层;
·broadcast:标识广播,它为发出的数据包添加了发送者地址,然后传递给abc模块;
·unicast:这个模块添加给数据包添加一个目标地址,再传递给broadcast模块。在接收端,如果数据包的目标地址和当前节点地址不符,该数据包将为丢弃。
·stunicast:当要求发送数据包至某个节点,它将在给定的时间周期内反复发送,直到要求停止。
·runicast:可信单播,它使用stunicast模块发送数据包,并等待确认报文,收到后停止持续重发数据包。为了防止无限次发送,必须指定一个最大重发次数。
·polite和ipolite:这两个模块几乎相同,当一个数据包必须在给定的时间帧内被发送,模块在到达时间的一半时,检查是否收到的数据包与它准备发送的相同。如果收到了,这个数据包将不被发送,否则发送。这是一个有效的泛洪技术,可以避免没必要的重发。
·multihop:这个模块要求一个路由表功能,当将要发送数据时它会请求路由表提供下一跳,并且使用unicast发送。当它收到一个数据包,如果本身即为目标节点就将数据包传至上层,否则再次请求路由表提供下一跳并转发。
MAC层
如我们所见,uIPv6协议栈使用了一个非常简单的MAC层协议称为sicsomac,没有其他选择。但是uIPv4协议栈使用Rime作为它的直接下层,因此可以选择MAC层协议。
以下是一些在Contiki上实现的MAC协议:
nullmac协议,正如其名,它什么都不做只是从更高层转发数据包至射频驱动,或者反向。
xmac协议,序文采样协议,节点周期性短时间监听射频频道。
lpp协议,探针协议,节点周期性发送一小段消息通知正在监听,之后监听一小段时间后休眠。