设为首页 加入收藏

TOP

Contiki学习笔记  第一个程序:Hello World(二)
2017-10-11 16:48:19 】 浏览:6487
Tags:Contiki 学习 笔记 一个 程序 Hello World
otothread.
小结:一系列动作下来观察到,PROCESS宏实际上就是给定一个name参数,此处可看做函数名称的一部分,生成一个静态函数,函数返回值为char,名称为process_thread_+name,函数里面有三个参数。结构体pt也是第二次碰到了(参考上一篇日志),就是一个数字。剩余两参数后面用到再回来讨论。
 
还没完,下面来分析第二句 struct process HW= { NULL, "HWP", process_thread_HW }
这里初始化了一个process结构体变量HW,上一篇日志我们已经分析了process结构,再贴上来看看
struct process {
      struct process *next;
      const char *name;
      char  (* thread)(struct pt *, process_event_t, process_data_t)
      struct pt pt;
      unsigned char state; 
      unsigned char needspoll;
};
结构体HW变量的第一个成员是指向下一元素指针,设为NULL,还未加入链表,只是NULL了。
第二个成员表示进程的名称,这里为"HWP",这是我们起的名字。
第三个成员,表示一个函数指针,每个process都有一个函数,process执行的就是这个函数,我们看看它的名字:process_thread_HW ,这不正是我们之前通过PT_THREAD展开的函数嘛。
还有三个参数没赋初值。
好,现在可以做一个总结了:
helloworld的第一句代码PROCESS(HW, "HWP");声明了此进程所对应的函数原型process_thread_HW ,还声明了此进程所对应的process结构体HW。并将函数原型作为HW的成员。
天啊,太复杂了,这才是第一句代码。
 
越来越有意思了,有些东西,外面看很抗拒,一旦钻进去,却又爱不释手。C语言一些简单的语法,能实现C#要非常复杂才能实现的功能。真是不同的世界观,准确地说,应该是让在不同的角度去看世界。继续分析第二句代码
AUTOSTART_PROCESSES(&HW);

先找到AUTOSTART_PROCESSES定义,在Autostart.h头文件中

#define AUTOSTART_PROCESSES(...)                    \
struct process * const autostart_processes[] = {__VA_ARGS__, NULL}
先上网查查__VA_ARGS__是什么:
__VA_ARGS__ 是一个可变参数的宏(gcc支持)。实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。这样预定义宏_ _VA_ARGS_ _就可以被用在替换部分中,替换省略号所代表的字符串。
经过替换,语句变成如下形式:
struct process * const autostart_processes[] = {&HW, NULL}
这里声明了一个指针数组,数组里的每一个指针都指向了一个process,数组声明的同时初始化了两个元素,第一个元素是指向HW的指针。回头看上一篇日志,HW正是表示当前process的结构体变量。这个数组用来做什么呢?后面用到再讲解。
下面继续讲解第三条语句:PROCESS_THREAD(HW, ev, data)
PROCESS_THREAD宏是老朋友了(请阅上一篇日志),专门用于生成process所要执行的函数原型。代入后的语句如下:
static char process_thread_HW(struct pt *process_pt, \ process_event_t ev, \ process_data_t data)
和上一篇日志展开后一样,上一次用于声明函数原型,这次声明的是函数主体。
  
继续第四条语句:PROCESS_BEGIN();
这个是关键,先找找宏定义,Process.h头文件中:
/** * Define the beginning of a process. *定义process的开始部分 * This macro defines the beginning of a process, and must always * appear in a PROCESS_THREAD() definition. The PROCESS_END() macro * must come at the end of the process. *此宏用于定义一个process的开始部分,并只能在PROCESS_THREAD() 函数体中定义。在process结尾处必须紧接着定义 *PROCESS_END() 宏。 */
#define PROCESS_BEGIN()             PT_BEGIN(process_pt)

继续代入吧,有啥可说的呢,语句变为:

PT_BEGIN(process_pt);

接下来找PT_BEGIN宏,Pt.h头文件中,原型如下:

/**
 * Declare the start of a protothread inside the C function
 * implementing the protothread.
 *用于在线程原型函数主体中声明一个线程的开始部分
 * This macro is used to declare the starting point of a
 * protothread. It should be placed at the start of the function in
 * which the protothread runs. All C statements above the PT_BEGIN()
 * invokation will be executed each time the protothread is scheduled.
 *此宏放在线程运行的开始部分。线程将会根据执行在PT_BEGIN()中声明的调用。
 * \param pt A pointer to the protothread control structure.
 * \hideinitializer
 */
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} LC_RESUME((pt)->lc);

代入,语句变为:

{ char PT_YIELD_FLAG = 1; if (PT_YIELD_FLAG) {;} LC_RESUME((process_pt)->lc)

整下容,变为

{ 
    char PT_YIELD_FLAG = 1; 
    if (PT_YIELD_FLAG) 
    {;} 
    LC_RESUME((process_pt)->lc);

继续追踪LC_RESUME宏:

#define LC_RESUME(s) switch(s) { case 0:

代入上式,最终PROCESS_BEGIN();变成:

{ 
    char PT_YIELD_FLAG = 1; 
    if (PT_Y
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Qt学习笔记 下一篇Beaglebone Black - 准备

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目