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

说明:这里就只是贴打印信息,分析打印信息了,不再贴分析过程中的代码了。

一,修改自己的hello-world.c文件内容如下:

 #include "contiki.h"

 #include <stdio.h> /* For printf() */
/*---------------------------------------------------------------------------*/
PROCESS(hello_world_process, "Hello world process");
PROCESS(test_process, "test process");
//AUTOSTART_PROCESSES(&hello_world_process);
AUTOSTART_PROCESSES(&hello_world_process, &test_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(hello_world_process, ev, data)
{
printf("\n\ntest hello_process...\n\n");
PROCESS_BEGIN();
PROCESS_YIELD(); printf("Hello, world\n"); PROCESS_END();
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(test_process, ev, data)
{
printf("\n\ntest test_process..\n\n");
PROCESS_BEGIN(); printf("Haha, only test\n"); PROCESS_END();
}

说明,上面代码就是在hello_process 这个process上添加了一个新的 test_process。这个test_process就是为了打印一个中国人的"Haha",不再是"Hello world"。

于是增加了第6行,以及第21~29行,修改了第8行。为了测试需要,在两个process函数体中,在PROCESS_BEGIN()之前,都添加了printf()语句。代码很简单,不做说明。

二,实现自己的contiki-main.c函数

这个就在 contiki-2.6/platform/native/ 下实现吧。只是把原来的contiki-main.c给备份了。

 #include <stdio.h>
#include <string.h>
#include "contiki.h" int
main(int argc, char **argv)
{ process_init(); autostart_start(autostart_processes); return ;
}

很简单了,初始化process,然后就自动启动hello-world.c里面的两个process.

<ps:同时,为了观察的更清楚,我去process.c/pt.h文件里也加入了一些printf(),比如一些函数中,我会加入printf("\n%s,%d\n",__func__,__LINE__);的代码,当然还有其他的一些printf()内容,不详述。所以,下面的打印中会多出一些内容。>

3,make,执行hello-world.native

 ./hello-world.native 

 process_init, 

 process_start,

 call_process, 

 test hello_process...

 PT_YIELD_FLAG =
PT_EXITED = , PT_ENDED = , PROCESS_EVENT_EXIT = ,PT_YIELDED = , ret = process_start, call_process, test test_process.. Haha, only test
process end: PT_YIELD_FLAG =
PT_EXITED = , PT_ENDED = , PROCESS_EVENT_EXIT = ,PT_YIELDED = , ret = exit_process,
exit_process, , and call call_process() call_process, test hello_process... PT_YIELD_FLAG =
Hello, world
process end: PT_YIELD_FLAG =
PT_EXITED = , PT_ENDED = , PROCESS_EVENT_EXIT = ,PT_YIELDED = , ret = exit_process,
exit_process, , and call call_process() call_process, exit_process, ok exit... exit_process, ok exit...

1,第三行---->main()中的process_init()执行。

2,第5行---->main()中的autostart_start(autostart_processes);执行。然后整个函数会在一个for()里面调用process_start()函数

3,第7行---->就是process_start()后,会牵涉出后面的process处理函数,这里已经到了call_process,意思是开始准备调用某个process了。

4,第10行--->在call_process()的作用下,我们自己的hello_process开始执行了。这里已经开始进入了hello_process的函数体了。

5,第13行--->检测出 (char) PT_YIELD_FLAG 的值为0。其实这已经执行到了hello_process中的 PROCESS_YIELD()宏了。这个宏在上文已经展开--如果PT_YIELD_FLAG 为0,会直接返回一个(PT_YIELDED = 1),而不会再接着执行下面的代码了。需要说明的是,PROCESS_YIELD()宏是位于PROCESS_BEGIN()宏后面,在PROCESS_BEGIN()中,已经将PT_YIELD_FLAG 初始化为 1了。但是在PROCESS_YIELD()中又被强制置0了。当然,PROCESS_YIELD还保存了当前所在行的行数,这是通过宏"__LINE__"来实现的。

6,第14行--->正如第5点所言,call_process在调用hello_process()函数后,因为PROCESS_YIELD()宏的作用,导致得到了一个返回值为 (PT_YIELDED =1)的结果。

7,第16行、第18行-->重新开了process_start ,call_process的执行。这其实是开始调用下一个process了。从这里可以看出,hello_process中的"Hello world"并没有执行,马上就把cpu的权利让给了下一个process--->类似于hello_process睡着了~~

8,第21行--->进入了test_process这个process的函数体。我在test_process中并没有再次使用PROCESS_YIELD()宏了,所以就顺风顺水的把test_process给执行完了。执行完毕后,把PT_YIELDED 写为0,这个动作是在 PROCESS_END()宏里完成。

9,第,27行--->test_process执行完毕,开始进入了exit阶段,准备释放自己的资源什么的,交出cpu控制权什么的。

10,第28行-->在exit阶段,test_process会把cpu控制权交给下一个相邻的process-->当然,最好的办法是启动这个process,于是可见,在exit阶段,call_process又一次被使用了。当然,test_process的邻process是hello_process,于是就直接启动了hello_process了。在这里有一点要说明,似乎test_process在exit的时候,仅仅是交出了cpu的控制权,但是是否真正exit了呢-->也就是所有的资源都释放了,不再占用了呢?

11,第30、33行,表明程序在一次进入了hello_process-->也即是,hello_process再一次开始执行,那么结果如何?

12,第36行,在PROCESS_YIELD()这个宏里面,检测到了PT_YIELD_FLAG 这个值为1,那就开始了下面代码的执行。需要说明的是,PROCESS_YIELD()里面有个case语句,它会和PROCESS_BEGIN()宏里面的switch匹配。而其工作原理,也其实类似于一个goto语句。这在上篇笔记已经说明了,不再赘述。

13,第37、39行,很无聊了,没必要再说。

14,第41行-->hello_process 准备exit了。

15,第42、44行,就是一个准备交出cpu控制权的过程了。但是貌似hello_process发现它的邻process是一个 NULL,于是一赌气,索性就全部exit了,包括控制权和资源。为嘛hello_process的邻process是一个NULL呢?因为process_list是一个链表,链表的终端指向了NULL,这在process_init()中就决定了它的命运。

16,第46、48行,exit了两次,这让我很惊讶,暂时没弄明白。等后面再补充。

ps: 原来准备在该笔记中,将整个process的流程再用一个流程图画一下,但由于打印的第46,48行,不知为啥会去执行两次,一时没明白,图片就暂时不画了,先研究下了。

贴一下,宏展开代码:

  static char process_thread_hello_world_process(struct pt *process_pt, process_event_t ev, process_data_t data)
{
printf("\ntest hello process!\n");
char PT_YIELD_FLAG = ;
if (PT_YIELD_FLAG) {;}
switch((process_pt) -> lc) {
case :
do {
PT_YIELD_FLAG = ;
(process_pt)->lc = __LINE__;
case __LINE__:
if(PT_YIELD_FLAG == ) {
return PT_YIELDED;
}
}while(); printf("Hello world ! \n");
};
PT_YIELD_FLAG = ;
process_pt->lc = ;
return PT_ENDED;
}

这个宏展开代码中,switch的用法很奇特,不过是正确的。其原理,已经在上篇笔记写明了。

好了,就这么多。

PROCESS_YIELD()宏使用及过程分析<contiki学习笔记之八>的更多相关文章

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

    好吧,我承认etimer有点小复杂,主要是它似乎和contiki的process搅在一起,到处都在call_process.那就先搜搜contiki下的etimer的example看看,然后再试着写一 ...

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

    这幅图片是对前面  <<contiki学习笔记之九>>  的一个补充说明. 简单的玩玩etimer <contiki学习笔记之九> 或许,自己正在掀开contiki ...

  3. PROCESS_YIELD()宏和C语言的switch语句< contiki学习笔记之七>

    写在前面:  按照main()函数的代码一行一行的分析,该是看到了 etimer_process 这个位置.但是etimer_process实现里的一个宏 PROCESS_YIELD()引出了很多故事 ...

  4. 【Visual C++】游戏编程学习笔记之八:鼠标输入消息(小demo)

     本系列文章由@二货梦想家张程 所写,转载请注明出处. 作者:ZeeCoder  微博链接:http://weibo.com/zc463717263 我的邮箱:michealfloyd@126.c ...

  5. contiki-main.c 中的process系列函数学习笔记 <contiki学习笔记之六>

    说明:本文依然依赖于 contiki/platform/native/contiki-main.c 文件. ---------------------------------------------- ...

  6. Contiki学习笔记  第一个程序:Hello World

    想来想去,还是得先写一个程序,找下感觉,增强一下自信心,那就国际惯例Hello World吧.先到这个网址下一个Instant Contiki 2.7.之所以没用3.0的,是因为有些问题,我源码是下的 ...

  7. contiki学习笔记---process结构体

    process,字面意义,进程,看看它的结构 struct process { struct process *next; #if PROCESS_CONF_NO_PROCESS_NAMES #def ...

  8. Contiki学习笔记

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

  9. python学习笔记之八:迭代器和生成器

    一. 迭代器 在前面的笔记中,已经提到过迭代器(和可迭代),这里会对此进行深入讨论.只讨论一个特殊方法---__iter__,这个方法是迭代器规则的基础. 1.1 迭代器规则 迭代的意思是重复做一些事 ...

随机推荐

  1. 查看buffer cache命中率

    SQL> select name,value from v$sysstat where name in('db block gets','consistent gets','physical r ...

  2. 【转】个人常用iOS第三方库以及XCode插件介绍 -- 不错

    原文网址:http://adad184.com/2015/07/08/my-favorite-libraries-and-plugins/ 第三方库是现在的程序员离不开的东西 不光是APP开发 基本上 ...

  3. windows批处理中的%0 %1 %2 %3

    原来就是参数的顺序.....倒...我还查了老半天

  4. ECSHOP v2.5数据库字典

    ECSHOP v2.5 数据库字典 ECSHOP R&D Team 2007年4月16日 商品相关表 商品分类表 category 此表用来维护商品分类信息 字段名 字段描述 字段类型 默认值 ...

  5. 【LeetCode 213】House Robber II

    This is an extension of House Robber. After robbing those houses on that street, the thief has found ...

  6. QT4.7.4-vs2008和vs2010的安装并编写测试程序

    QT的安装着实费了我好大的劲,之前试过QT5.1.0与VS2010的安装,但是因为设置的地方太多,程序运行总是不成功,所以最后选用QT4.7.4和VS2008与VS2010来编写程序.写这篇文章来总结 ...

  7. 【跟我一起学Python吧】Python 多线程

    其实自我感觉Python的多线程很类似于Java的多线程机制,但是比JAVA的多线程更灵活.在早期的Python多线程实现中,采用了thread模块.例如: from time import ctim ...

  8. 微软控制台带来的PHP控制台输出问题

    /** * 测试文件包含方式对跨平台的影响 * 控制台下测试. * 默认的文件编码为 UTF-8 */ function testChinese() { $file = __DIR__ . '/con ...

  9. 软件开发杂谈之从需求到上线---valen

    背景 IT已经成为当代企业必不可少的竞争手段,从无到有到标配,可以说以后不懂IT的就是文盲这句一点也不过,而软件开发是个复杂工程,零零碎碎各种理论工具和技巧,一言难尽. 本文意在言简意赅,简述软件开发 ...

  10. Codevs No.1281 Xn数列

    2016-06-01 16:28:25 题目链接: Xn数列 (Codevs No.1281) 题目大意: 给定一种递推式为 Xn=(A*Xn-1+C)%M 的数列,求特定的某一项%G 解法: 矩阵乘 ...