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

全部博文(87)

文章存档

2014年(10)

2013年(24)

2012年(53)

我的朋友

分类: 嵌入式

2012-10-12 21:18:01

 

         contiki 所有进程都必须调用 process_start()函数,才能运行起来。系统初始化的时候, process_start(&etimer_process, NULL);必须显示的启动时间进程,这个函数调用后,就会启动本线程。

 

        那用户自己的进程呢,有些进程是需要手动的启动起来(至于其他进程,等还没搞清楚),需要自动运行的程序要添加到struct process * const autostart_processes[];这个数组里面,然后在主程序候总调用autostart_start(autostart_processes);就可以把将这些进程自动的启动,比如

AUTOSTART_PROCESSES(&print_hello_process,&print_world_process);  

 

下面是autostart_start函数,它就是讲存放在全局变量autostart_process[]里面的所有进程调用process_start 函数,依次启动起来。

 

 

 

autostart_start(struct process * const processes[])
{
  int i;
  
  for(i = 0; processes[i] != NULL; ++i) {
    process_start(processes[i], NULL);
    PRINTF("autostart_start: starting process '%s'\n", processes[i]->name);
  }
}

 

下面是process_start函数:

       process_start所干的工作就是:

         1.先把将要执行的进程加入到进程队列process_list的首部,如果这个进程已经在process_list中,就return;
        2.接下来就把state设置为PROCESS_STATE_RUNNING并且初始化pt的lc为0(这一步初始化很重要,关系到protothread进程模型的理解)。
         3.最后通过函数process_post_synch()给进程传递一个PROCESS_EVENT_INIT事件,让其开始执行,看看这个函数的定义:

void
process_start(struct process *p, const char *arg)
{
  struct process *q;

  /* First make sure that we don't try to start a process that is
     already running. */
  for(q = process_list; q != p && q != NULL; q = q->next);


  /* If we found the process on the process list, we bail out. */

  if(q == p) {

    return;

  }

  /* Put on the procs list.*/

  p->next = process_list;

  process_list = p;

  p->state = PROCESS_STATE_RUNNING;

  PT_INIT(&p->pt);


  PRINTF("process: starting '%s'\n", p->name);


  /* Post a synchronous initialization event to the process. */

  process_post_synch(p, PROCESS_EVENT_INIT, (process_data_t)arg);

}

 

        上面process_start最后调用了process_post_synch()这个函数是同步投递函数的,也就是事件投递过去,另外一个进程就要运行起来。下面是process_process_post_synch()的实现部分,由于process_current 是全局变量,指向当前正在运行的进程,此时,process_current将会指向你传递过来的进程。而你传递过来的进程可能会退出或者被挂起等待一个事件,而如果它没有引起新的进程运行,那么系统要知道谁调用的此进程,然后返回到老的 process_current 让系统继续运行下去,所以,这里必须要保存当前的process_current,所以用临时变量记录 *caller,记录了下来。

 

void

process_post_synch(struct process *p, process_event_t ev, process_data_t data)

{

  struct process *caller = process_current;

  call_process(p, ev, data);

  process_current = caller;

}

 

 

      将时间使用  process_post_synch 投递后,真正启动进程的操作是由call_process来完成的。下面是call_process 的代码:

 

 

假如进程process的状态是PROCESS_STATE_RUNNING以及进程中的thread函数不为空的话,就执行这个进程:
1.首先把process_current指向p;
2.接着把process的state改为PROCESS_STATE_CALLED;
3.执行hello_world这个进程的body也就是函数p->thread,并将返回值保存在ret中,如果返回值表示退出或者遇到了PROCESS_EVENT_EXIT的时事件后,便执行exit_process()函数,process退出。不然程序就应该在挂起等待事件的状态,那么就继续把p的状态维持为PROCESS_STATE_RUNNING。

static void

call_process(struct process *p, process_event_t ev, process_data_t data)

{

  int ret;


#if DEBUG

  if(p->state == PROCESS_STATE_CALLED) {

    printf("process: process '%s' called again with event %d\n", p->name, ev);

  }

#endif /* DEBUG */


  if((p->state & PROCESS_STATE_RUNNING) &&

     p->thread != NULL) {

    PRINTF("process: calling process '%s' with event %d\n", p->name, ev);

    process_current = p;

    p->state = PROCESS_STATE_CALLED;

    ret = p->thread(&p->pt, ev, data);//这是进程的实体------函数,这里就是真正的执行了进程,实际上就是调用函数。函数执行完毕后,返回到这里,它的状态会改变,下面根据情况再处理。

    if(ret == PT_EXITED ||

       ret == PT_ENDED ||

       ev == PROCESS_EVENT_EXIT) {

      exit_process(p, p);

    } else {

      p->state = PROCESS_STATE_RUNNING;

    }

  }

}

 

 

      在call_process里面由引入了一个exit_process()函数;

static void

exit_process(struct process *p, struct process *fromprocess)

{

  register struct process *q;

  struct process *old_current = process_current;


  PRINTF("process: exit_process '%s'\n", p->name);


  if(process_is_running(p)) {

    /* Process was running */

    p->state = PROCESS_STATE_NONE;


    /*

     * Post a synchronous event to all processes to inform them that

     * this process is about to exit. This will allow services to

     * deallocate state associated with this process.

     */

    for(q = process_list; q != NULL; q = q->next) {//向所有的进程发送退出事件,其他进程会根据此时间标志,进行一些相关的处理,比如要退出的进程使用了etimer事件,etimer_process就会查找timerlist看看哪个timer是与这个进程相关的,就把它从timerlist中清除

      if(p != q) {


call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p);

      }

    }


    if(p->thread != NULL && p != fromprocess) {      //向要退出的进程发送事件,前提是,要退出的进程不能使当前运行的进程。可能是A进程要求B进程退出,此时A进程要向B进程发送一个事件,因为B进程可能希望在自己退出的时候,再执行一些操作。类似与 钩子函数 或者 析构函数?

      /* Post the exit event to the process that is about to exit. */

      process_current = p;

      p->thread(&p->pt, PROCESS_EVENT_EXIT, NULL);

    }

  }


  if(p == process_list) {

    process_list = process_list->next;

  } else {

    for(q = process_list; q != NULL; q = q->next) {

      if(q->next == p) {


q->next = p->next;


break;

      }

    }

  }


  process_current = old_current;

}

 

 

        exit_process函数有两个参数,前一个是要退出的process,后一个是当前的process。
        在这个进程要退出之前,必须要给所有的进程都要发送一个PROCESS_EVENT_EXITED事件,告诉所有与之相关的进程它要走了,如果收到这个事件的进程与要死的进程有关的话,自然会做出相应的处理(一个典型的例子是,如果一个程序要退出的话,就会给etimer_process进程发送一个PROCESS_EVENT_EXITED事件,那么收到这个事件之后,etimer_process就会查找timerlist看看哪个timer是与这个进程相关的,就把它从timerlist中清除)。

       如果要退出的process就是当前的process,那么就只需要把它从进程列表中清除即可;如果要退出的process不是当前的process,那么当前的process就要给要退出的process传递一个PROCESS_EVENT_EXIT事件让其进程的body退出,然后再将其从进程列表中清除。

 

 

 

 

 

 

引用贴:

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



 

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