Contiki学习笔记:主要数据结构之事件

7218阅读 0评论2011-10-20 Jelline
分类:嵌入式

摘要:

    本文介绍了Contiki主要数据结构之事件,深入源码分析事件结构体,图示事件队列,并介绍事件处理和新事件加入是如何影响事件队列的。


一、事件

1.1 事件结构体

事件也是Contiki重要的数据结构,其定义如下:

  1. struct event_data
  2. {
  3.   process_event_t ev;
  4.   process_data_t data;
  5.   struct process *p;
  6. };

  7. typedef unsigned char process_event_t;
  8. typedef void * process_data_t;

各成员变量含义如下:

ev-----标识所产生事件

data---保存事件产生时获得的相关信息,即事件产生后可以给进程传递的数据

p------指向监听该事件的进程

1.2 事件分类

    事件可以被分为三类:时钟事件(timer events)、外部事件、内部事件。那么,Contiki核心数据结构就只有进程和事件了,把etimer理解成一种特殊的事件。


二、 事件队列

Contiki用环形队列组织所有事件(用数组存储),如下:

  1. static struct event_data events[PROCESS_CONF_NUMEVENTS];

图示事件队列如下:

上图源文件,点这里下载 Contiki事件队列图示.rar   

三、系统定义的事件

3.1 系统事件

系统定义了10个事件,源码和注释如下:

  1. /*配置系统最大事件数*/
  2. #ifndef PROCESS_CONF_NUMEVENTS
  3.   #define PROCESS_CONF_NUMEVENTS 32
  4. #endif

  5. #define PROCESS_EVENT_NONE            0x80 //函数dhcpc_request调用handle_dhcp(PROCESS_EVENT_NONE,NULL)
  6. #define PROCESS_EVENT_INIT            0x81 //启动一个进程process_start,通过传递该事件
  7. #define PROCESS_EVENT_POLL            0x82 //在PROCESS_THREAD(etimer_process, ev, data)使用到
  8. #define PROCESS_EVENT_EXIT            0x83 //进程退出,传递该事件给进程主体函数thread
  9. #define PROCESS_EVENT_SERVICE_REMOVED 0x84
  10. #define PROCESS_EVENT_CONTINUE        0x85 //PROCESS_PAUSE宏用到这个事件
  11. #define PROCESS_EVENT_MSG             0x86
  12. #define PROCESS_EVENT_EXITED          0x87 //进程退出,传递该事件给其他进程
  13. #define PROCESS_EVENT_TIMER           0x88 //etimer到期时,传递该事件
  14. #define PROCESS_EVENT_COM             0x89
  15. #define PROCESS_EVENT_MAX             0x8a /*进程初始化时,让lastevent=PROCESS_EVENT_MAX,即新产生的事件从0x8b开始,函数process_alloc_event用于分配一个新的事件*/

注:PROCESS_EVENT_EXIT与PROCESS_EVENT_EXITED区别

    事件PROCESS_EVENT_EXIT用于传递给进程的主体函数thread,如在exit_process函数中的p->thread(&p->pt, PROCESS_EVENT_EXIT, NULL)。而PROCESS_EVENT_EXITED用于传递给进程,如call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p)。(助记:EXITED是完成式,发给进程,让整个进程结束。而g一般式EXIT,发给进程主体thread,只是使其退出thread)

3.2 一个特殊事件

    如果事件结构体event_data的成员变量p指向PROCESS_BROADCAST,则该事件是一个广播事件(为么不用一个特殊事件来标识广播事件,而采用这种费解方式?)。在do_event函数中,若事件的p指向的是PROCESS_BROADCAST,则让进程链表process_list所有进程投入运行。详情见详情见博文《Contiki学习笔记:深入理解process_run函数》2.2,部分源码如下:

  1. #define PROCESS_BROADCAST NULL //广播进程

  2. /*保存待处理事件的成员变量*/
  3. ev = events[fevent].ev;
  4. data = events[fevent].data;
  5. receiver = events[fevent].p;

  6. if (receiver == PROCESS_BROADCAST)
  7. {
  8.   for (p = process_list; p != NULL; p = p->next)
  9.   {
  10.     if (poll_requested)
  11.     {
  12.       do_poll();
  13.     }
  14.     call_process(p, ev, data);
  15.   }
  16. }

上一篇:Contiki学习笔记:主要数据结构之进程
下一篇:Contiki学习笔记:主要数据结构之etimer