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

全部博文(87)

文章存档

2014年(10)

2013年(24)

2012年(53)

我的朋友

分类: 嵌入式

2012-10-12 20:00:27

     1,mian()

       {

       初始化;

       process_init();

        process_start(&etimer_process, NULL);

 

  autostart_start(autostart_processes);

 

   while(1)

   {

 

     ..........

    process_run();

      .........

 

 }

 

    2,程序的主体部分。

 

 

#include "contiki.h"

#include "debug-uart.h"


/*步骤2:用PROCESS宏声明进程执行主体,并定义进程*/

PROCESS(example_1_process,"Example 1");//PROCESS(name, strname)    

PROCESS(example_2_process,"Example 1");


/*步骤3:用AUTOSTART_PROCESSES宏让进程自启动*/

AUTOSTART_PROCESSES(&example_1_process,&example_2_process);//AUTOSTART_PROCESSES(...)    


/*步骤4:定义进程执行主体thread*/

PROCESS_THREAD(example_1_process,ev,data)//PROCESS_THREAD(name, ev, data)

{

  PROCESS_BEGIN();  /*代码总是以宏PROCESS_BEGIN开始*/


  /*example_1_process的代码*/


  PROCESS_END();  /*代码总是以宏PROCESS_END结束*/

}


PROCESS_THREAD(example_2_process,ev,data)

{

  PROCESS_BEGIN();


  /*example_2_process的代码*/


  PROCESS_END();

}

 

 

     先声明,然后调用AUTOSTART_PROCESSES来初始化一个全局数组,这是一个宏,在预处理阶段就会处理掉,在main()执行前,数组已经初始化完毕。然后在主程序里执行到  autostart_start,它会调用 process_start,process_start 会将此进程加入process_list,并初始化此进程的lc=0,然后调用了process_post_synch(p, PROCESS_EVENT_INIT, (process_data_t)arg);此时将一个PROCESS_EVENT_INIT 事件传了过来,而arg=NULL。   process_post_synch()  调用call_process()将参数 传递过来,call_process 改变下状态,就开始执行

 

    p->state = PROCESS_STATE_CALLED;
    ret = p->thread(&p->pt, ev, data);

    

   由于contiki是CRT机制,所以会一直运行到此process阻塞或者退出

 if(ret == PT_EXITED ||
       ret == PT_ENDED ||
       ev == PROCESS_EVENT_EXIT) {
      exit_process(p, p);
    } else {
      p->state = PROCESS_STATE_RUNNING;
    }

 

  如果要退出,调用exit_process,如果是阻塞,设置下状态就会返回了,返回到process_post_synch 找出上次正在执行的process,然后返回到调用process_post_synch的位置,继续执行,process_current = caller;就绪下去,如果这个进程也阻塞,则再次先前返回,找到更先前的process_current。。。。。。类似与递归的概念, 一层层入栈 入栈,执行完之后再出栈,不同点在于,事件机制可以在出栈的过程再次入栈,就在一个栈里面来回捣鼓

 

 

接下来给出三种程序基本结构(即顺序、选择、循环)的模式。

二、顺序&选择&循环

2.1 顺序

PROCESS_BEGIN();

(*...*)

PROCESS_WAIT_UNTIL(cond1);//注1

(*...*)

PROCESS_END();

2.2 循环

PROCESS_BEGIN();

(*...*)

while(cond1)

  PROCESS_WAIT_UNTIL(cond1 orcond2);//注1

(*...*)

PROCESS_END();

2.3 选择

PROCESS_BEGIN();

(*...*)

if(condtion)

  PROCESS_WAIT_UNTIL(cond2a);//注1

else

  PROCESS_WAIT_UNTIL(cond2b);//注1

(*...*)

PROCESS_END();

    注1:这里不一定非得用宏PROCESS_WAIT_UNTIL,事实上有很多选择,比如宏PROCESS_WAIT_EVENT_UNTIL(c)、宏PROCESS_WAIT_EVENT()、宏PROCESS_YIELD_UNTIL(c)等(请参见本文第三部分),实际编程应根据实际情况加以选择。

三、挂起进程相关API

3.1 概述

    表1给出挂起进程相关API的功能描述,事实上,实际编程所关心的是,什么时候继续执行宏后面的内容,3.2~3.6给出了详见分析。

表1 Contiki挂起进程相关API[1]

 

 

3.2 PROCESS_WAIT_EVENT和PROCESS_YIELD

    从代码展开来看,宏PROCESS_WAIT_EVENT和宏PROCESS_YIELD实现的功能是一样的(或者说PROCESS_WAIT_EVENT只是PROCESS_YIELD的一个别名),只是两种不同的描述。也就是说当PT_YIELD_FLAG为1时(即该进程再次被调度的时候,想想PROCESS_BEGIN宏包含语句PT_YIELD_FLAG=1),才执行宏后面的代码,否则返回。代码展开如下:

#define PROCESS_WAIT_EVENT()PROCESS_YIELD()

#define PROCESS_YIELD()PT_YIELD(process_pt)


#define PT_YIELD(pt)                \

  do

  {                        \

    PT_YIELD_FLAG =0;                \

    LC_SET((pt)->lc);                \

    if(PT_YIELD_FLAG ==0)

    {            \

      returnPT_YIELDED;            \

    }                        \

  }while(0)

3.3 PROCESS_WAIT_EVENT_UNTIL和PROCESS_YIELD_UNTIL

    根3.2类似,宏PROCESS_WAIT_EVENT_UNTIL和宏PROCESS_YIELD_UNTIL是一组,在3.2的基础是增加了额外的一个条件,也就是说当PT_YIELD_FLAG为1且条件为true时(即进程再次被调度的时候,条件为true,因为PROCESS_BEGIN宏已包含语句PT_YIELD_FLAG),才执行宏后面的代码,否则返回。代码展开如下:

#define PROCESS_WAIT_EVENT_UNTIL(c)PROCESS_YIELD_UNTIL(c)

  #define PROCESS_YIELD_UNTIL(c)PT_YIELD_UNTIL(process_pt,c)


  #define PT_YIELD_UNTIL(pt,cond)        \

  do

  {                        \

    PT_YIELD_FLAG =0;                \

    LC_SET((pt)->lc);                \

    if((PT_YIELD_FLAG ==0)||!(cond))

    {    \

      returnPT_YIELDED;            \

    }                        \

  }while(0)

3.4 PROCESS_WAIT_UNTIL和PROCESS_WAIT_WHILE

    从代码展开来看,宏PROCESS_WAIT_UNTIL和宏PROCESS_WAIT_WHILE判断的条件相反,PROCESS_WAIT_UNTIL宏当条件为真时(即某个事件发生),执行宏后面的内容。而PROCESS_WAIT_WHILE宏当条件为假时,执行宏后面的内容(即当条件为真时,阻塞该进程)。

/*PROCESS_WAIT_UNTIL宏展开*/

#define PROCESS_WAIT_UNTIL(c)PT_WAIT_UNTIL(process_pt,c)


/*PROCESS_WAIT_WHILE宏展开*/

#define PROCESS_WAIT_WHILE(c)PT_WAIT_WHILE(process_pt,c)

#define PT_WAIT_WHILE(pt,cond)PT_WAIT_UNTIL((pt),!(cond))


/*PT_WAIT_UNTIL宏展开*/

#define PT_WAIT_UNTIL(pt,condition)     \

  do

  {                        \

    LC_SET((pt)->lc);                \

    if(!(condition))

    {                \

      returnPT_WAITING;            \

    }                        \

  }while(0)

3.5 PROCESS_PT_SPAWN

    PROCESS_PT_SPAWN用于产生一个子protothread,若执行完thread并退出PT_EXITED,则继续执行宏PROCESS_PT_SPAWN后面的内容。宏一层层展开如下:

#define PROCESS_PT_SPAWN(pt,thread)PT_SPAWN(process_pt,pt,thread)

#define PT_SPAWN(pt,child,thread)        \

  do

  {                        \

    PT_INIT((child));                \

    PT_WAIT_THREAD((pt),(thread));        \

  }while(0)

  

#define PT_WAIT_THREAD(pt,thread)PT_WAIT_WHILE((pt),PT_SCHEDULE(thread))


#define PT_WAIT_WHILE(pt,cond)PT_WAIT_UNTIL((pt),!(cond))


#define PT_SCHEDULE(f)((f)<PT_EXITED)

3.6 PROCESS_PAUSE

    宏PROCESS_PAUSE用于向进程传递事件PROCESS_EVENT_CONTINUE,被挂起了宏展开如下如下:

#define PROCESS_PAUSE()

do

{                \

  process_post(PROCESS_CURRENT(),PROCESS_EVENT_CONTINUE,NULL);    \

  PROCESS_WAIT_EVENT();                            \

}while(0)

 

 

     这个很好理解,就是自己给自己发送了个事件,PROCESS_EVENT_CONTINUE,这个不过是标示而已,然后系统会去执行其他的代码,直到do_event时,此进程收到自己发给自己的事件,就可以继续运行了。也就是暂停了以下,就继续运行下去了。

3.7 PROCESS_WAIT_EVENT_UNTIL与PROCESS_WAIT_UNTIL区别

    从上述3.3和3.4代码展开可以看出,宏PROCESS_WAIT_EVENT_UNTIL和宏PROCESS_WAIT_UNTIL的区别在于:

PROCESS_WATI_EVENT_UNTIL  是一定会导致进程阻塞的,即使里面条件是满足的,也会阻塞到下次调度。这个API首先要求,要阻塞,此进程下面代码是无论如何不能执行下去了,必须阻塞,但是再次执行下去的条件是,有事件来了,并且附加条件也满足,才可以运行了。

 

PROCESS_WAIT_UNTIL,它是说,进程并非已经达到了不能执行的地步,只要条件是满足的,那么就会执行下去,不一定会导致阻塞

 

 

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

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