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. }
时间: 2024-07-31 07:50:19

Contiki 学习笔记:????process_run 解析的相关文章

简单的玩玩etimer <contiki学习笔记之九>

好吧,我承认etimer有点小复杂,主要是它似乎和contiki的process搅在一起,到处都在call_process.那就先搜搜contiki下的etimer的example看看,然后再试着写一个demo玩玩. 在写demo之前,先说说自己是怎么找到etimer 的example的文件的. 在core/sys/etimer.h 文件中,在描述etimer的数据结构的时候,作者显示的指出,如果要使用etimer,就必须先使用 etimer_set()这个函数进行一些工作,如图: 是的,数据结

简单的玩玩etimer <contiki学习笔记之九 补充>

这幅图片是对前面  <<contiki学习笔记之九>>  的一个补充说明. 简单的玩玩etimer <contiki学习笔记之九> 或许,自己正在掀开contiki process最后的一层面纱: 或许,还有一段路要走: 或许,已经掀开... --------------- 一切,都只是process:只有有了process,才会轮到etimer_process  发言,除非,抛却一切机制,裸机实现etimer... process,是什么? 一个链表,还是单向的,仅此

contiki-main.c 中的process系列函数学习笔记 &lt;contiki学习笔记之六&gt;

说明:本文依然依赖于 contiki/platform/native/contiki-main.c 文件. ------------------------------------------------------------------------------------------------------------------------------------- 根据上一个笔记里面添加的printf()语句的打印信息提示,hello world 打印是在执行了 1 autostart_

PROCESS_YIELD()宏和C语言的switch语句&lt; contiki学习笔记之七&gt;

写在前面:  按照main()函数的代码一行一行的分析,该是看到了 etimer_process 这个位置.但是etimer_process实现里的一个宏 PROCESS_YIELD()引出了很多故事,于是单独把整个宏的东西整理成笔记,贴出来,和学习contiki的伙伴分享. 在说这个宏之前,得先记下c 语言的switch()遭遇. switch()从表面上来看,或许应该是非常简单的问题--C语言的基本功吧.它的使用方式,按照常规来说,如下图所示: 好吧,那就贴一段常规的代码: 1 int ma

PROCESS_YIELD()宏使用及过程分析&lt;contiki学习笔记之八&gt;

好吧,昨晚上研究了switch()的底层实现原理--发现它并不是一般C语言教科书上那样所言,当然,这对于本身就非常熟悉汇编的同学来说,是小菜一碟.世界上,很多事情是巧合与必然的结合体,没有无缘无故的爱,也没有无缘无故的恨---我为啥会被一个switch给挡出去路?这个switch在contiki中又有何重要作用?且不回答这个问题,先来看看如何使用昨天晚上展开的PROCESS_YIELD()宏. 说明:这里就只是贴打印信息,分析打印信息了,不再贴分析过程中的代码了. 一,修改自己的hello-wo

javaSE学习笔记DOM4J解析(7)

DOM4J即Document Object Model for Java使用java技术以文档方式解析XML数据的模型. DOM4J是开源组织提供的一个免费的.强大的XML解析工具,如果开发者需要在项目中使用那么需要下载并引入jar包. dom4j is an Open Source XML framework for Java. dom4j allows you to read, write, navigate, create and modify XML documents. dom4j i

JavaWeb学习笔记——XML解析

DOM解析操作 只在跟节点<addresslist>下面建立一个子节点<name> <?xml version="1.0" encoding="UTF-8"?> <addresslist> <linkman> <name>张三</name> <email>www.baidu.com</email> </linkman> <linkman>

javaSE学习笔记SAX解析(6)

SAX即Simple Api for Xml就是一个简单的操作XML数据的一套SUN提供的API机制. SAX采用的解析的原理是基于事件触发的机制. SAX技术只能进行XML数据的读取. 1.准备需要解析的XML文件linkmans.xml<?xml version="1.0" encoding="UTF-8" standalone="no"?> <linkmans> <linkman> <name>

jquery学习笔记---each解析json数据

使用jQuery解析JSON数据 在上一篇的Struts2之ajax初析中,我们得到了comments对象的JSON数据,在本篇中,我们将使用jQuery进行数据解析. 我们先以解析上例中的comments对象的JSON数据为例,然后再小结jQuery中解析JSON数据的方法. 上例中得到的JSON数据如下,是一个嵌套JSON: {"comments":[{"content":"很不错嘛","id":1,"nickn