Chinaunix首页 | 论坛 | 博客
  • 博客访问: 393230
  • 博文数量: 87
  • 博客积分: 1171
  • 博客等级: 少尉
  • 技术积分: 1068
  • 用 户 组: 普通用户
  • 注册时间: 2012-09-19 14:34
文章分类

全部博文(87)

文章存档

2014年(10)

2013年(24)

2012年(53)

我的朋友

分类: 嵌入式

2012-10-12 20:35:03

contiki 主要数据结构

 

1:进程的数据结构

struct process {
  struct process *next;
#if PROCESS_CONF_NO_PROCESS_NAMES
#define PROCESS_NAME_STRING(process) ""
#else
  const char *name;
#define PROCESS_NAME_STRING(process) (process)->name
#endif
  PT_THREAD((* thread)(struct pt *, process_event_t, process_data_t));
  struct pt pt;
  unsigned char state, needspoll;
};

 

1.因为要维持一个进程的链表,struct process *next是指向它的下一个进程,声明一个process时初始化为0;
2.const char *name指的是这个进程的名字;
3.第三个展开来就是 char (* thread)(struct pt *, process_event_t, process_data_t),thread是一个函数指针,也就是说process包含了一个函数,每个process都包含了一个函数,process的执行其实就是这个函数体的执行。
4.再来看看pt的定义:

struct pt {

  lc_t lc;  //typedef unsigned short lc_t;

};

struct pt pt在这有何用,这正是protothread的精髓所在,看contiki内在ls-switch.h文件里的一段说明:
This implementation of local continuations uses the C switch()statement to resume execution of a function somewhere inside the function's body. The implementation is based on the fact that switch() statements are able to jump directly into the bodies of control structures such as if() or while() statements.

上面已经提到过lc表示local continuation,它是为switch()语句服务的,保留process的pt值,在下一次process执行的时候便可通过switch语句直接跳到要执行的语句,从而可以恢复process的执行,实现对process的控制。
5.还有unsigned char state, needspoll,state表示process的状态,具体定义在process.h文件中;一般process初始化的时候needspoll的值为0,假如needspoll的值为1的话,可以优先执行,具体先不深入讨论。

 

 

          简而言之,needspoll为1的进程有更高的优先级。具体表现为,当系统调用process_run()函数时,把所有needspoll标志为1的进程投入运行,而后才从事件队列取出下一个事件传递给相应的监听进程。 

    与needspoll相关的另一个变量poll_requested,用于标识系统是否存在高优先级进程,即标记系统是否有进程的needspoll为1。

staticvolatileunsigned charpoll_requested;

 

 

     2 事件

 

    2.1 事件数据结构

 

structevent_data

{

  process_event_t ev;

  process_data_t data;

  structprocess*p;

};


typedef unsigned charprocess_event_t;

typedef void*process_data_t;

 

 

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

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

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

 

 

1.2 事件分类

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

 

二、 事件队列

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

    static   struct   event_data events[PROCESS_CONF_NUMEVENTS];

 

 

图示事件队列如下:

 

三、系统定义的事件

3.1 系统事件

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

/*配置系统最大事件数*/

#ifndef PROCESS_CONF_NUMEVENTS

  #define PROCESS_CONF_NUMEVENTS 32

#endif


#define PROCESS_EVENT_NONE            0x80 //函数dhcpc_request调用handle_dhcp(PROCESS_EVENT_NONE,NULL)

#define PROCESS_EVENT_INIT            0x81 //启动一个进程process_start,通过传递该事件

#define PROCESS_EVENT_POLL            0x82 //在PROCESS_THREAD(etimer_process, ev, data)使用到

#define PROCESS_EVENT_EXIT            0x83 //进程退出,传递该事件给进程主体函数thread

#define PROCESS_EVENT_SERVICE_REMOVED 0x84

#define PROCESS_EVENT_CONTINUE        0x85 //PROCESS_PAUSE宏用到这个事件

#define PROCESS_EVENT_MSG             0x86

#define PROCESS_EVENT_EXITED          0x87 //进程退出,传递该事件给其他进程

#define PROCESS_EVENT_TIMER           0x88 //etimer到期时,传递该事件

#define PROCESS_EVENT_COM             0x89

#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所有进程投入运行。部分源码如下:

#define PROCESS_BROADCAST NULL//广播进程


/*保存待处理事件的成员变量*/

ev =events[fevent].ev;

data =events[fevent].data;

receiver=events[fevent].p;


if(receiver==PROCESS_BROADCAST)

{

  for(=process_list;!=NULL;=p->next)

  {

    if(poll_requested)

    {

      do_poll();

    }

    call_process(p,ev,data);

  }

}

 

 

 

一、定时器概述

    Contiki包含一个时钟模型和5个定时器模型(timer, stimer, ctimer, etimer, and rtimer)[1],5种timer简述如下:

timer--be used to check if a time period has passed[1]

stimer--be used to check if a time period has passed[1]

ctimer--Active timer, calls a functionwhen it expires, Used by Rime[2]

etimer--Active timer, sends an event whenit expires[2]

rtimer--Real-time timer, calls a functionat an exact time[2]

注:

    (1) timer与stimer区别在于the resolution of time:timers use system clock ticks while stimers use seconds to allow much longer time periods[1]。

    (2) Unlike the other timers, the timer and stimer libraries can be safely used from interrupts which makes them especially useful in low level drivers.

 

 

 

    timer仅包含起始时刻和间隔时间,所以timer只记录到期时间。通过比较到到期时间和新的当前时钟,从而判断该定时器是不是到期。

2.2 timerlist

全局静态变量timerlist,指向系统第一个etimer,图示timerlist如下:

staticstructetimer *timerlist;

 

 


 

http://blog.chinaunix.net/uid-9112803-id-2976929.html

阅读(1420) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~