码迷,mamicode.com
首页 > 其他好文 > 详细

第12章 纤程(Fiber)

时间:2015-09-23 01:12:36      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:

12.1 纤程对象的介绍

(1)纤程与线程的比较

比较

线程(Thread)

纤程(Fiber)

实现方式

是个内核对象

在用户模式中实现的一种轻量级的线程,是比线程更小的调度单位。

调度方式

由Microsoft定义的算法来调度,操作系统对线程了如指掌。内核对线程的调度是抢占式的。

由我们自己调用SwitchToFiber来调度,内核对纤程一无所知。线程一次只能执行一个纤程代码,纤程间的调度不是抢占式的。

备注

一个线程可以包含一个或多个纤程。操作系统随时可能夺走纤程所在线程的运行。当线程被调度时,当前被选择的纤程得以运行,而其他纤程无法运行,因为同一个线程中,每次只能有一个纤程正在运行,除非调用SwitchToFiber才能切换到另一个纤程去执行。与SwitchToThread不同,SwitchToFiber会立即切换到另一个纤程去执行(如果该线程的CPU时间还有剩余的话),而SwitchToThread要等CPU来调度另一个线程。

纤程与线程一样,也有自己的寄存器环境与函数调用栈

(2)纤程的执行上下文的构成(类似线程上下文)——大约200个字节

  ①用户自定义的值,它被初始化为传给ConvertThreadToFiber的pvParam参数的值

  ②结构化异常处理链的头

  ③纤程栈顶部和底部的内存地址(当我们将一个线程转换为一个纤程时,这时也是线程栈)

  ④某些CPU寄存器,其中包括栈指针、指令指针以及其他寄存器(注意,默认下不包含CPU的浮点状态信息)

(3)纤程运行动态示意图

技术分享 

★注意:

  在同一个线程里创建的两个纤程之间的切换是很安全的(如图中A箭头),但跨线程间的两个纤程的切换是不安全的(如图中的B、C箭头)。因为纤程本质上是由线程调度的,假设某个时刻,线程2正在调用纤程2.2,但在纤程2.2的内部调用了SwitchToFiber切换到了纤程1.2。如果CPU的下一个时间周期仍给线程2,因为内核并不知道纤程的切换,所以此时CPU仍会试图去执行纤程2.2的代码,但由于纤程的切换,会导致线程2的堆栈环境发生了变化,此时再去执行纤程2.2就可能会出现错误。

12.2 纤程的使用

(1)创建主纤程:CreateThreadToFiber(pvParam)(将已有线程转为纤程,该线程才能调用其它纤程API函数,可理解为启动线程的纤程模式

  ★注意:

    ①返回值为纤程的上下文环境,可以理解为返回一个纤程对象。

    ②默认情况下,x86 CPU的FPU信息不会被纤悉无纤程保存下来,因此在进行浮点运算时,可能破坏数据。为避免此情况,要调该新的ConvertThreadToFiberEx函数,并为dwFlags传入FIBER_FLAG_FLOAT_SWITCH标志。

(2)创建纤程(可理解为子纤程):CreateFiber

参数

描述

DWORD dwStackSize

纤程栈大小。一般传入0,表示系统自动分配

PFIBER_START_ROUTINE

  pfnStartAddress

纤程函数,原型为

VOID WINAPI FiberFunc(PVOID pvParam)

PVOID pvParam

传给纤程函数的额外参数。

  ★注意:

    ①返回值为纤程的上下文环境,可以理解为返回一个纤程对象。

    ②同样,为防止发生浮点运算事故,可以调用新的API函数CreateFiberEx,并传入FIBER_FLAG_FLOAT_SWITCH标志。

(3)纤程的调度SwitchToFiber(PVOID pvFiberExcutionContext)函数,其中的参数是CreateFiber或CreateThreadToFiber返回的纤程对象(即纤程上下文环境)。注意:SwitchToFiber是让纤程得到CPU时间的唯一方法!由于我们必须显示调用SwitchtoFiber来让纤程有机会得到执行,因此纤程的调度完全在我们的掌握之中。

  ①SwitchToFiber函数的内部运行

  A.将一些CPU寄存器当前值(包括指令指针寄存器和栈指针寄存器),保存到当前正在运行的纤程的执行上下文中。

  B.从即将运行的纤程的执行上下文中,将先前保存的寄存器载入CPU寄存器。使用当线程继续执行的时候,会使用新纤程的运行环境(如栈、指令指针)

  C.将新纤程上下文与线程关联起来,让线程运行指定的纤程。

  D.将线程的指令指针设为新纤程先前保存的指令指针,这样线程(纤程)就会从上次执行的地方开始继续往下执行。

(4)纤程的删除:DeleteFiber(PVOID pvFiberExecutionContext);

  ①当纤程执行结束后,调用该函数来销毁纤程,被删除的纤程的栈将被销毁,纤程执行的上下文也会被释放。

  ②如果纤程是ConvertThreadToFiber转换得到的主纤程,当调用DeleteFiber相当于调用ExitThread直接终止线程。如果不希望终止线程,可以调用ConvertFiberToThread将主纤程转回线程,这里也会释放原来调用ConverThreadToFiber将线程转化为纤程时所占用的最后一块内存。注意,ConvertFiberToThread只转换主纤程,对其它子纤程无效

【Fiber程序】

 

第12章 纤程(Fiber)

标签:

原文地址:http://www.cnblogs.com/5iedu/p/4830983.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!