原始线程(protothreads)

来源:互联网 发布:微信打不开链接淘宝 编辑:程序博客网 时间:2024/04/29 13:54

详细说明:“原始线程”是一种轻量级的、无需堆栈的线程。它主要用于内存极为受限的系统,如深入嵌入式系统、传感器网络等。
“原始线程”是以C代码实现的,为事件驱动的系统提供了线性的代码执行空间。“原始线程”即可以用在有实时操作系统的系统中,也可以用在没有实时操作系统的系统中。
它在事件驱动的系统上层提供了阻塞上下文,省去了每个线程的单独堆栈空间开销。原始线程的目标是在没有复杂的状态机或多线程的情况下实现控制顺序流。原始线程在C语言内部实现了条件阻塞。
原始线程相对于纯事件驱动方法的优势是原始线程提供了可以阻塞函数的顺序代码结构。在纯事件驱动的方法中,阻塞的实现必须将一个函数手动分成两个部分。一部分放在阻塞调用前,一部分放在阻塞调用后。这让使用if()和while()语句变得困难。
原始线程相对于普通线程的优势是,它不需要为每个线程分配堆栈。在内存受限的系统中,为每个线程分配堆栈空间会占用大量的内存。相比而言,原始线程的每个线程只需2到12个字节的状态字,具体多大与构架有关。
注意:
由于原始线程有阻塞调用中中不需保存堆栈上下文,原始线程阻塞时,局部变量也不再保留。这意味着局部变量的使用必须十分小心。如果不确定的话,尽量不要有原始线程中使用局部变量。
主要特性:

 

· 无机器相关代码-代码完成是C写的。 

· 不使用错误-倾向于像longjump()这样的函数。 

· 很小的RAM开销-每条线程仅两个字节。 

· 即可使用OS,也可以不使用。 

· 提供阻塞等待而无需多线程或堆栈切换。

主要应用:

 

· 内存受限系统 

· 事件驱动的协议栈 

· 深入嵌入式系统 

· 传感器网络

原始线程包括四个基本的操作:初妈化(PT_INIT()),执行(PT_BEGIN()),条件阻塞(PT_WAIT_UNTIL()),和退出(PT_EXIT()).在此之上还有两个方便使用的函数:反向条件阻塞(PT_WAIT_WHILE())和原始线程阻塞(PT_WAIT_THREAD()).
见:uIP中文文档第五 原始套接字
原始线程线的分布是基于一个类似于BSD的协议的。也就是说允许商业的和非商业的使用。唯的需要是"credit is given".

 

原始线程:原始线程是极端轻量级的、无需堆栈的线程。它在事件驱动的系统上层提供阻塞上下文,无需为每个线程提供堆栈的开销。原始线程的目标是在没有复杂的状态机或多线程的情况下实现控制顺序流。原始线程在C函数内部实现了条件阻塞。
在内存受限的系统中,如深入嵌入式系统,传统的多线程的内存开销可能会显得过大。在传统线程中每条线程都需要自己堆栈,这种要求并非必要的。堆栈空间可能花去大部分的内存空间。
原始线程相对于多线程的优势在于原始线程是相当轻量极的,原始线程不需要自己的堆栈。相反,所有的线程都运行在同一个堆栈中,上下文的切换是通过堆栈的回转实现的。这在内存受限的系统中是具有优势的,因为那里一个线程的堆栈可能就占用了很大的一部分内存。原始线程的每条线程只需两字节,而且原始线程是纯用C实现的,不需要任何机器有关的汇编语言代码。
一个原始线程在一个C语言函数中运行,不能跨过多个函数。原始线程可以调用普通的C语言函数,在调用的C语言函数不能阻塞。嵌套调用的函数内部的阻塞是通过为可以阻塞的函数产生一人新的线程来实现的。这种方法的优点是阻塞是明确的,程序员确切的知道哪些函数是可以阻塞的,哪些函数是永远也不会阻塞的。
原始线程与不对称的协同程是相似的,主要的不同在于协同程序为每个协同程序使用单独的堆栈而原始线程无需堆栈。与原始线程最相似的机制是Python产生器。这些产生器也是无堆栈的结构,但用途不同。原始线程在C函数内部实现阻塞上下文,而python产生器从产生函数中提供了多个退出点。
局部变量:
注意:
由于原始线程有阻塞调用中中不需保存堆栈上下文,原始线程阻塞时,局部变量也不再保留。这意味着局部变量的使用必须十分小心。如果不确定的话,尽量不要有原始线程中使用局部变量。
调度:
原始线程是通过重复调用宿主函数驱动的。每调用宿主函数一次,原始线程都会运行到阻塞或退出为止。这样说来,原始线程的高度是由使用原始线程的应用做到的。
实现:
原始线程的实现采用了"local continuation"机制."local continuation"代表的是一个程序在某个位置的当前执行状态,但不提供任何调用历史或局部变量."local continuation"可以在指定函数内设定,以捕获程序的状态."local continuation"设定后可以恢复,以复原"local continuation"设定时函数的状态.
"local continuation"的实现的多种方法:
1. 使用机器相关的汇编语言
2. 使用标准C结构体.
3.使用编译器扩展.
第一种方式通过保存和恢复处理器状态实现,所说的处理器状态不包括堆栈指针.这种方式每个原始线程需要16到32个字节的内存空间,具体是多少与处理器构架有关.
标准C语言的实现方式每个线程只需要2字节,它以一种不明显的方式优化了C语言中的switch()语句,这与Duff的设备类似.然而,这种实现对使用原始线程的代码稍有限制,不能在代码中使用switch()语句.
某些编译器有C语言的扩展也可以实现原始线程.比如说GCC支持标签指针,这就可以用于此目的.在这种实现方式下,每个原始线程需要4字节内存.

 

文件:
ft.h 原始线程的实现
模块:
Local continuation 实现原始线程的基础
数据结构:
struct pt
初始化:
#define PT_INIT(pt) 初始化原始线程
声明和定义:
#define PT_THREAD(name_args) 声明原始线程
#define PT_BEGIN(pt) 在要实现原始线程的函数内部声明原始线程的开始
#define PT_END(pt) 声明原始线程的结尾
阻塞等待:
#define PT_WAIT_UNTIL(pt,condition) 等待直到条件为真.
#define PT_WAIT_WHILE(pt,cond) 等待只要条件为真.
分级的原始线程:
#define PT_WAIT_THREAD(pt,thread) 阻塞等待子线程完成
#define PT_SPAWN(pt,child,thread) 产生子进程并等待其结束.
退出和重启:
#define PT_RESTART(pt) 重启原始线程
#define PT_EXIT(pt) 退出原始线程
调用原始线程:#define PT_SCHEDULE(pt) 高度原始线程
原始线程让位:
#define PT_YIELD(pt) 当前原始线程让位(即暂时中止,让别的线程先执行).
#define PT_YIELD_UNTIL(pt) 面前原始线程让位,直到条件为真.
定义:
#define PT_WAITING 0
#define PT_EXITED 1
#define PT_ENDED 2
#define PT_YIELDED 3 

 

1. #define PT_BEGIN(pt)在实现原始线程的C函数中声明原始线程开始.
此宏用于声明原始线程的开始点.应该把它放在使用原始线程的函数的开头儿.放在此句之前的C语句每次原始线程的调度都会执行一次.
参数:
pt 指向线程控制结构的指针
应用例程:
dhcpc.c.
定义于pt.h115行.

 


2. #define PT_END(pt) 
声明原始线程的结尾
此宏用于声明原始线程的结尾,它通常必须与PT_BEGIN()宏匹配使用.
参数:
pt 指向原始线程控制结构的指针.
应用例程:
dhcpc.c
定义于pt.h127行.

 


3. #define PT_EXIT(pt)
退出原始线程
此宏使用始线程退出.如果退出的线程是一个子线程,则其父线程结束阻塞状态,得以继续运行.
参数:
pt 指向原始线程控制结构的指针.
定义于pt.h246行.

 


4. #define PT_INIT(pt) 
初始化原始线程.初始化必须在使用之前完成.参数:
pt 指向原始线程控制结构的指针.
见:PT_SPAWN()
应用例程:
dhcpc.c. 
定义于pt.h80行.
引用于
httpd_appcall().

 



5. #define PT_RESTART(pt)
重启原始线程.此宏会致使运行的线程从PT_BEGIN()处重新开始执行.
参数:
pt 指向原始线程控制结构的指针.

应用例程:
dhcpc.c
定义于pt.h229行.

 



6. #define PT_SCHEDULE(f)调试线程,此函数调度线程,如果调度的线程在运行则此函数返回非零值,如已经退出,则返回零值.
参数:
f  要调度的线程的宿主函数的调用.
定义于ph.h271行.

 


7. #define PT_SPAWN(pt,child,thread) 此宏用于产生一个子线程并等待直到子线程的退出 .它只能用于线程内部.
参数:
pt 指向线程控制结构的指针.
child 指向子线程的控制结构的指针.
带参数的子线程.
定义于pt.h206行.

 



8.#define PT_THREAD(name_args)
此宏用于声明原始线程,所有的原始线程都必须由此声明.
应用例程:
dhcpc.c 和smtp.c
定义于pt.h100行.

 


9. #define PT_WAIT_THREAD(pt,thread)
阻塞并等待子线程无成.
这个宏调度了一个子线程,并等待子线程的完成 .
注意:
在此函数使用之前,子原始线程必须通过PT_INIT()初始化.
参数:
pt 指向原始线程控制结构体的指针.
thread 带有参数的子线程.
定义于pt.h192行.

 



10. #define PT_WAIT_UNTIL(pt,condition)
阻塞等待,直到条件为真.
此宏阻塞线程直到指定的条件为真.
参数:
pt 指向原始线程控制结构体的指针.
condition 指定的条件.

应用例程:
dhcpc.c .
定义于pt.h148行.

 



11. #define PT_WAIT_WHILE(pt,cond) 
阻塞等待,直到条件为真.
此宏阻塞线程只要指定的条件为真.

参数:
pt 指向原始线程控制结构体的指针.
condition 指定的条件.
定义于pt.h167行.

 



12. #define PT_YIELD(pt)
从当前线程中让位.
这个函数会让当前线程让位,从而使其它线程先在系统中运行.
参数:
pt 指向原始个线程控制结构体的指针.
应用例程:
dhcpc.c.
定义于pt.h290行.

 


13. #define PT_YEILD_UNTIL(pt,cond)
使当前线程让位,直到某条件发生.
参数:
pt 指向原始线程控制结构的指针.
cond 条件.
此函数会让当前线程让位,直到某条件为真.
定义于pt.h310行.

0 0
原创粉丝点击