Contiki 学习笔记:process_run 解析

process_run用于处理系统所有needspoll标记为1的进程及处理事件队列的下一个事件。本文深入原码,详细分析,也包括do_poll和do_event函数。


一、运行process_run

  1. int main()
  2. {
  3. dbg_setup_uart();
  4. usart_puts("Initialising\n");

  5. clock_init();
  6. process_init();
  7. process_start(&etimer_process, NULL);
  8. autostart_start(autostart_processes);

  9. while (1)
  10. {
  11. /*执行完所有needspoll为1的进程及处理完所有队列*/
  12. do
  13. {
  14. }
  15. while (process_run() > 0);
  16. }
  17. return 0;
  18. }

二、process_run剖析

process_run处理系统所有needspoll标记为1的进程及处理事件队列的下一个事件,源代码如下:

  1. static volatile unsigned char poll_requested; //全局静态变量,标识系统是否有needspoll为1的进程

  2. int process_run(void)
  3. {
  4. if (poll_requested) //进程链表有needspoll为1的进程
  5. {
  6. do_poll(); //见2.1
  7. }

  8. do_event(); //见2.2

  9. return nevents + poll_requested; //若和为0,则表示处理完系统的所有事件,并且没有needspoll为1的进程
  10. }

透过上述的源代码,可以直观看出needspoll标记为1的进程可以优先执行。并且每执行一次process_run,将处理系统所有needspoll标记为1的进程,而只处理事件队列的一个事件。

2.1 do_poll函数

复位全局变量poll_requested,遍历整个进程链表,将needspoll标记为1的进程投入运行,并将相应的needspoll复位。源代码如下:

  1. static void do_poll(void)
  2. {
  3. struct process *p;
  4. poll_requested = 0; //复位全局变量

  5. for (p = process_list; p != NULL; p = p->next) //处理所有needspoll为1的进程
  6. {
  7. if (p->needspoll) //将needspoll为1的进程投入执行
  8. {
  9. p->state = PROCESS_STATE_RUNNING;
  10. p->needspoll = 0;
  11. call_process(p, PROCESS_EVENT_POLL, NULL);
  12. }
  13. }
  14. }

2.2 do_event函数

do_event处理事件队列的一个事件,有两种事件需特殊处理:PROCESS_BROADCAST和PROCESS_EVENT_INIT。前者是广播事件,需处理所有进程,后者是初始化事件,需将进程状态设为PROCESS_STATE_RUNNING。源代码如下:

  1. static process_num_events_t nevents; /*事件队列的总事件数 */
  2. static process_num_events_t fevent; /*指向下一个要传递的事件的位置*/
  3. static struct event_data events[PROCESS_CONF_NUMEVENTS]; /*事件队列,用数组存储,逻辑上是环形队列*/

  4. static void do_event(void)
  5. {
  6. /*以下3个变量恰为struct event_data的成员,用于暂存即将处理(fevent事件)的值*/
  7. static process_event_t ev;
  8. static process_data_t data;
  9. static struct process *receiver;

  10. static struct process *p;

  11. if (nevents > 0)
  12. {
  13. /*提取将要处理事件的成员变量*/
  14. ev = events[fevent].ev;
  15. data = events[fevent].data;
  16. receiver = events[fevent].p;

  17. fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS; //更新fevent(指向下一个待处理的事件,类型于微机的PC)
  18. --nevents; //事件队列被组织成环形队列,所以取余数

  19. if (receiver == PROCESS_BROADCAST) //如果事件是广播事件PROCESS_BROADCAST,则处理所有进程
  20. {
  21. for (p = process_list; p != NULL; p = p->next)
  22. {
  23. if (poll_requested)
  24. {
  25. do_poll();
  26. }
  27. call_process(p, ev, data); //jelline note: call the receiver process twice??
  28. }
  29. }
  30. else
  31. {
  32. if (ev == PROCESS_EVENT_INIT) //若事件是初始化,设置进程状态,确保进程状态为PROCESS_STATE_RUNNING
  33. {
  34. receiver->state = PROCESS_STATE_RUNNING;
  35. }
  36. call_process(receiver, ev, data);
  37. }
  38. }
  39. }
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值