Contiki常用数据结构
1. Packetbuf
得益于Contiki进程是非抢占的特性,Rime缓冲区将接收与发送的数据包存储在一个单一的缓冲区packetbuf,它的管理结构如图1.1所示,结合该图与源代码packetbuf.c可以很好地理解和使用缓冲区。
特别注意packetbufptr,该指针可以指向外部引用的内存,这样就带来很大的灵活性(如:实现“零拷贝”,访问只读数据区等)。
图1.1 Rime缓冲区管理示意图
为了有效利用底层MAC和链接层协议,rime buffer使用数据包属性取代数据包头,即图1.2所示的packetbuf_attrs。另外,记录了接收与发送数据包的地址信息,即packetbuf_addrs。
图1.2 Rime数据包属性与地址示意图
2. RimeQueueBuf
上节描述可知Packetbuf简单实用,但它只能保存一个数据包,如果协议需要缓存发送数据包(例如:排队发送)就需要队列性质的数据结构。图2.1所示,左图存储“非引用类型”的packetbuf,包括:数据包、属性和地址;右图存储“引用类型”的packetbuf,包括:数据包头部、引用内存的指针。
图2.1非引用和引用类型的queuebuf数据结构
Contiki内存管理是基于预先分配,queuebuf的大小由以下宏定义控制:QUEUEBUF_NUM对应struct queuebuf的个数、QUEUEBUF_RAM_NUM对应struct queuebuf_data的个数、QUEUEBUF_REF_NUM对应struct queuebuf_ref的个数,一般说来前2个宏定义个数相等。
图2.2可配置个数的queuebuf
RimeQueueBuf保存与恢复“非引用内存”packetbuf的原理如图2.3所示。
图2.3保存与恢复“非引用内存”packetbuf
RimeQueueBuf保存与恢复“引用内存”的packetbuf的原理如图2.4所示。
图2.4保存与恢复“引用内存”
3. LIST
Contiki遵循Linux的“万能链表”设计思想,即LIST数据结构。只要将实际链表对象的第一个域配置成void *next,即可使用LIST的常见操作:开辟链表头空间、插入节点和删除节点,即图3.1所示。
图3.1 LIST常见操作
4. MEMB
Contiki的内存分配采用预先设置的方式,当申明一块内存MEMB(name, structure, num)时,即开辟如图4.1所示的内存空间,其中name_memb_count[]记录该内存块引用的次数,name_memb_mem[]是num个大小为sizeof(structure)的静态内存。
图4.1开辟内存空间
图4.2分配内存
当执行memb_alloc()成功分配内存时,该内存的引用次数加一,返回该内存的指针,如图4.2所示。回收内存是分配内存的逆过程,memb_free()会将该内存的引用次数减一。
图4.3回收内存
5. ctimer
ctimer的主要用途是为contiki的协议栈提供定时器,从图5.1所示的ctimer数据结构可知,它的定时功能是通过etimer来实现的。
图5.1 ctimer数据结构
当用户调用ctimer_set()函数插入一个ctimer后,ctimer_list结构如图5.2所示,当该定时器到期后会被系统自动从链表中摘除,即图5.3效果,如果用户需要继续定时则要再次调用ctimer_set()添加该定时器。
图5.2添加一个ctimer定时器
图5.3 ctimer定时器到期后从链表中摘除
图5.4显示了一个ctimer定时器的调用时序,当call_process调用ctimer_set()后,经过interval时长后etimer_process检测到该定时器超时并发送消息给ctimer_process,ctimer_process调用该定时器注册的回调函数。这里有一个小技巧:在回调函数执行前会将process_current赋值为ctimer_i->p,这样做保持了进程轨迹的一致性。
图5.4 ctimer定时器调用时序
6. etimer
图6.1显示了一个etimer定时器插入前、插入后和超时调用后,这三种情况下etimer链表数据结构。很容易看出,当一个etimer超时并处理后它将从链表中摘除,如果用户需要再次使用该定时器则需要继续调用etimer_set()函数。
图6.1 etimer链表结构
Etimer的调用时序如图6.2所示,call_process调用etimer_set()添加一个etimer定时器后,经过interval时长该定时器超时,这里etimer_process向call_process发送超时消息,当call_process接收到超时消息后执行对应的逻辑动作。
图6.2 etimer调用时序
作者简介:
蒋俊,男,硕士研究生,现任长沙市锐米通信科技有限公司CEO。
从事通信研究与嵌入式开发10年,主攻微功率无线网络。
精通LoRa无线扩频通信,无线星型/树型/MESH网络设计;
通晓Contiki,Linux,uC/OS-II,OSAL等操作系统;
熟悉ARM,DSP,STM8,PIC,PC104等处理器;
擅长AD,RF等集成IC开发。
Web: www.rimelink.com
EMail: jiangjunjie_2005@126.com
QQ群:35212129