/**
\addtogroup sys
@{
*/
/**
\defgroup pt Protothreads
Protothread 是一种轻型,栈使用少的线程。这种线程为,如嵌入式系统或传感器结点,等内存受限系统而设计。
Protothread用C实现了事件驱动系统的线性执行速度的代码。Protothread可以用于或不用于RTOS(实时系统)。
Protothread是一种优秀的轻型,栈小的线程。它提供了在事件驱动系统上的阻塞机制,且没有传统线程的开销。Protothread的目的是不使用复杂的状态机或者传统线程(full multi-threading)。Protothread提供了在C函数内部的条件阻塞。
Protothread与单纯的事件驱动方法相比优势在于,它为阻塞函数提供了顺序代码结构。在纯粹的事件驱动系统中,必需人为地将函数分为两部分:一部分代码用于阻塞调用前,另一部分代码用于阻塞调用后。这使它很难使用if或者while等控制结构。
Protothread与传统线程( ordinary threads)相比的优势是Protothread不需要独立的栈空间。在内存受限系统中,分配多线程栈空间的开销会浪费大量可用的内存。相比之下,由于架构不同(即芯片架构),每一个Protothread只需要2个到12个状态字节。
\note
因为Protothread在阻塞调用时,不保存堆栈信息,所以在使用Protothread线程阻塞时,不保存局部变量。这意味着,在使用局部变量时,要十分小心。如果拿不准,在Protothread线程中,不要使用局部变量。
主要特性:
——没有特殊的汇编代码——Protothrea库文件,全部用C写成
——没有用易于出错的函数,像longjmp()
——很小的RAM开销——每个Protothread线程只要两个字节
——可以使用或不使用OS。
——提供没有传统多线程(full multi-threading )或栈切换的阻塞等待
应用举例:
——内存受限系统
——事件驱动协议栈
——深度嵌入式系统
——传感器网络节点
Protothread线程API有四种基本操作组成:
初始化:PT_INIT();
执行:PT_BEGIN();
条件阻塞:PT_WAIT_UNTIL();
退出:PT_END()。
除了以上这些,为了方便,实现了两个函数:
反相条件阻塞(reversed condition blocking,拿不准确):PT_WAIT_WHILE();
Protothread阻塞:PT_WAIT_THREAD();
\sa \ref pt "Protothreads API documentation"
Protothread线程库采用BSD-style License,它允许商业和非商业使用。The only requirement is that credit is given。
\section authors Authors
Protothread线程库,由Adam Dunkels写就,得到了Oliver@sics.se> Schmidt的帮助。
\section pt-desc Protothreads@web.de>
Protothread是一种优秀的轻型,栈小的线程。它提供了在事件驱动系统上的阻塞机制,且没有传统线程的开销。Protothread的目的是不使用复杂的状态机或者传统线程(full multi-threading)。Protothread提供了在C函数内部的条件阻塞。
在内存受限系统中,如深度嵌入式系统,传统多线程(traditional multi-threading)或许存在很大的内存开销。在传统的多线程中,每个线程需要自己独立的栈空间。这些栈空间,或许使用了大量可用的内存。
Protothread与传统线程( ordinary threads)相比,主要优势在于Protothread十分轻量型:一个Protothread线程不需要独立的栈空间,而是所有的Protothread线程使用同一个栈空间。任务切换( context
switching)通过栈覆盖( stack rewinding)完成。这在内存受限系统中有很大的优势。在这些系统中,栈对应一个线程(全部内存只有一个堆栈,所有线程共同使用这一个堆栈),或许有大量可用内存。每个Protothread只需要两个字节。而且,Protothread完全使用C实现,没有任何特定的汇编代码。
Protothread运行在单一的C函数内,且不能跨函数使用。一个Protothread或许可以调用一般的C函数,但是不能在被调函数中阻塞。将潜在阻塞的函数写成一个单独的Protothread,替代调用内部嵌套阻塞的函数。这种写法的优势在于阻塞是显式的,我们清楚地了解哪一个函数阻塞了,哪一个函数不会阻塞。
Protothread线程有些像co-routins协程(本质上一种轻量级的线程,几种架构:多进程,多线程,非阻塞/异步IO(callback),Coroutine模型)。本质的区别在于,每个Coroutine协程需要独立的栈空间,而protothread使用栈空间很少。和protothread机制最像的是Python生成器。它也是一种使用栈空间少的结构,但是目的不一样。Protothread在一个C函数内部阻塞任务(blocking contexts),而Python生成器提供一个多退出口的生成函数。
\section pt-autovars Local variables
\note
由于Protothread在调用阻塞时,不保护栈内容。在protothread阻塞时,不保存局部变量。这意味着,在使用局部变量时,要十分小心。如果拿不准,不要在protothread中使用局部变量。
\section pt-scheduling Scheduling
每一次发生调用时,protothread将运行到它阻塞或退出。
因此,由使用protothread的应用程序,完成protothread的调度。
\section pt-impl Implementation
Protothread使用lc(local continuations)实现。一个lc(local continuation)表示执行时在程序中的实际位置(即函数的状态),但是没有保存任何调用记录和局部变量。lc(local continuation)在一个特定的函数内设定,以捕获函数的状态(即运行的实际位置)。在lc(local continuation)已经设置的地方,可以恢复到函数设置它的状态。
lc可以有多种实现方式:
——#使用特定的汇编代码
——#使用标准C的结构
——#使用编译器扩展
第一种方法,是保存和恢复除栈指针外的处理器状态,每个protothread需要16-32个字节内存,确切需要的内存量取决于内核架构(芯片的内核结构)。
使用标准C实现,每个protothread仅需2字节。使用隐式的switch语句像是 Duff's device(见注1)。
然而,这种实现对于代码引入了一个小小的限制,即在使用protothread线程的代码中,不能使用switch语句。
一些编译器有C扩展,可以用来实现protothread。GCC支持标签指针(label pointers),它可以用于实现protothread。这种扩展使每个protothread需要4个字节(即一个指针的大小)的内存空间。
@{
*/
/** @} */
/** @} */
注:
1、http://blog.csdn.net/subkiller/article/details/5987944
Duff's device
文章评论(0条评论)
登录后参与讨论