[资料] ProtoThreads如何工作的(转)
1077 查看
19 回复
 楼主 | 发布于 2018-08-28 | 只看楼主
分享到:

最近把手头的SD卡更新NKNAND项目完成,总算抽空上网瞎逛游了。正好群里面有人推荐了一个系统,说是对小资源的单片机非常适合。这里我就推荐2篇网文:

http://www.daxia.com/bibis/moredata30_1234764_43130.shtml

http://blog.csdn.net/t_larry/archive/2008/10/18/3097191.aspx

2篇网文一个讲系统简介,一个是里面宏的说明。熟悉一下是很不错的。

然后就是官网了:

http://www.sics.se/~adam/pt/index.html

我翻译了里面的under the hood 章节:How protothreads really work

(0 ) (0 )
回复 举报

楼主 | 回复于 2018-08-28 沙发

What goes on behind the magical macros in the C protothreads library? Why are they macros? How do the macros work? Read on for the explanation.

在C protothreads库里面的神奇宏到底发生了什么?他们为什么都是宏?这些宏是如何工作的?请接着读解释:

 

In the C implementation of protothreads, all protothread operations are hidden behind C macros. The reason for building the protothread library on C macros rather than C functions is that protothreads alter the flow of control. This is typically difficult to do with C functions since such an implementation typically would require low-level assembly code to work. By implementing protothreads with macros, it is possible for them to alter the flow of control using only standard C constructs.

在Protothreads系统C的实现里,所有的protothread操作都被隐藏在C的宏里面。生成protothread库用C的宏而不是用C函数的原因是protothreads需要改变程序的跳转,这通常是很难用C函数做,因为这样的实现通常需要低级别的汇编代码的工作。通过protothreads宏的实施,它有可能只使用标准C结构为他们改变程序的跳转。

 

This page explains how protothreads work under the hood. We do this by taking a look at how the C preprocessor expands the protothread macros, and by looking at how the resulting C code is executed.

这页介绍了protothreads在这个hood下如何工作。我们来看看protothread C预处理宏如何工作,如何生成C代码被执行。
(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 2#

First, we'll introduce a simple example program written with protothreads. Since this is a simple program we can show the entire program, including the main() function from which the protothread is driven. The code, shown below, waits for a counter to reach a certain threshold, prints out a message, and resets the counter. This is done in a while() loop that runs forever. The counter is increased in the main() function.

首先,我们将介绍一个简单的用protothreads写的例子程序。由于这是一个简单的程序就可以显示整个程序,包括main()函数启动protothreads。代码如下所示,等待计数器达到一定的阈值就打印出一条消息,并重置计数器。这是在一个while()循环里运行下去的。计数器是在main()函数里面增加。


(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 3#

1.	#include “pt.h”  
2.	  
3.	static  int  countrer;  
4.	static  struct  pt  example_pt;  
5.	  
6.	static  PT_THREAD(example(struct  pt  *pt1))  
7.	{  
8.	  PT_BEGIN(pt1);  
9.	  while(1) {  
10.	    PT_WAIT_UNTIL(pt1,counter == 5);  
11.	    printf("Threshold reached/n");  
12.	    counter = 0;  
13.	  }  
14.	  PT_END(pt1);  
15.	}  
16.	  
17.	int main(void)  
18.	{  
19.	       counter = 0;  
20.	       PT_INIT(&example_pt);  
21.	  
22.	       while(1){  
23.	              example(&example_pt);  
24.	              counter++;  
25.	       }  
26.	       return 0;  
27.	}  
(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 4#

Before we let the C preprocessor expand the above code, we'll take a look at how the protothread macros are defined. In order to make things easier, we use a simpler definition than the actual definition from the protothreads source code. (The definition used here is a combined version of the protothread macros and the local continuation macros implemented with the C switch statement.) This definition looks like:

在我们让C预处理器解析表面代码之前,我们先讨论下protothread的宏是如何定义的。为了方便起见,我们使用一个比protothreads源代码的实际代码简单的代码例子。(这里使用的定义是protothread宏和本地延续宏与C switch语句结合的组合版本。)这个定义是这样的:


(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 5#



(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 6#

We see that the struct pt consists of a single unsigned short called lc, short for local continuation. This unsigned short variable is the source of the "two byte overhead" frequently mentioned on the protothread web pages. Furthermore, we see that the PT_THREAD macro simply puts a char before its argument. Also, we note how the PT_BEGIN and PT_END macros open and close a C switch statement, respectively. But the PT_WAIT_UNTIL macro is the most complex looking of them all. It contains one assignment, one case statement, one if statement, and even a return statement! Also, it uses the built-in __LINE__ macro twice. The __LINE__ macro is a special macro that the C preprocessor will expand to the line number at which the macro is issued. Finally, the PT_INIT macro simply initializes the lc variable to zero.

我们看到这个结构体pt包括一个unsigned short 变量lc,对应本地short类型。这unsigned short变量是protothread网页里面提到的2字节内存开销。此外,我们看到PT_THREAD宏简单的把char放在它的参数前面。另外我们注意到PT_BEGINPT_END宏是如何打开与关闭一个C swithc结构的起始、结束。但是PT_WAIT_UNTIL宏是这些宏里面最复杂的。它包括一个任务,一个case语句,一个if语句甚至有一个return语句!另外,它使用2次内置的_LINE_宏。_LINE_宏是一个特殊的能够让C预处理器解析当前使用宏的行号的宏。最后,PT_INIT宏简单的将lc变量初始化为0
(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 7#

Many of the statements used in the protothread macros are not commonly used in macros. The return statement used in the PT_WAIT_UNTIL macro breaks the flow of control in the function the macro is used. For this reason, many people dislike the use return statements in macros. The PT_BEGIN macro opens a switch statement, but does not close it. The PT_END macro closes a compound statement that it has not itself opened. These things does look weird when looked at without the perspective of protothreads. However, in the context of protothreads these things are absolutely essential to the correct operation of protothreads: the macros has to change the flow of control in the C function in which they are used. This is indeed the whole point of protothreads.

protothread宏里面使用的很多语句在宏运行状态是不常使用的。return语句在PT_WAIT_UNTIL宏中的使用跳出了当前使用宏的程序流程。因此,很多人不喜欢在宏里面添加return语句。PT_BEGIN宏打开了一个switch语句,但是没有关闭它。PT_END宏关闭一个不是它打开的复合语句。这些代码如果不是从protothread的角度来看会很奇怪。然而,在protothreads的背景下,这些代码是绝对必不可少的正确操作:这些在C函数中使用的宏改变了控制流,这的确是protothreads的重点。


(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 8#

Ok, enough of talk about how the protothread macros look weird to seasoned C developers. We now instead look at how the protothread in the example above looks when expanded by the C preprocessor. To make it easier to see what is happening, we put the original and the expanded versions side by side.

好了,现在可以谈论下protothread宏在C语言开发里面是如此的怪异。我们现在不要去看例子里面扩展了C预处理命令的protothread。为了让它看起来更容易一些,我们把源代码与替换了宏的代码放一起。
(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 9#

(0 )
评论 (0) 举报

楼主 | 回复于 2018-08-28 10#

At the first line of the code we see how the PT_THREAD macro has expanded so that the example() protothread has been turned into a regular C function that returns a char. The return value of the protothread function can be used to determine if the protothread is blocked waiting for something to happen or if the protothread has exited or ended.

在代码的第一行我们看到PT_THREAD宏展开使得protothread example()变成一个返回char类型的普通C函数。 protothread函数的返回值能够用来确定protothread是在线程等待或者是该protothread已经退出或结束。

 

The PT_BEGIN macro has expanded to a PT(switch) statement with an open brace. If we look down to the end of the function we see that the expansion of the PT_END macro contains the closing brace for the switch. After the opening brace, we see how the PT_BEGIN expansion contains a case 0: statement. This is to ensure that the code after the PT_BEGIN statement is the first to be executed the first time the protothread is run. Recall that PT_INIT set pt->lc to zero.

PT_BEGIN宏展开一个包含大括号的PT switch结构。如果我们往下看就能看到PT_END宏包含对应switch结构的结束大括号。在开始大括号后面,我们能够看到PT_BEGIN包含一个case 0:部分。这是确保protothread运行以后,在PT_BEGIN部分后面的代码第一次执行。调用PT_INIT设置pt->lc0


(0 )
评论 (0) 举报
发表回复
0/3000





举报

请选择举报类别

  • 广告垃圾
  • 违规内容
  • 恶意灌水
  • 重复发帖

全部板块

返回顶部