纤 程
Windows添加一种纤程,以便能够非常容易地将现有的 UNIX服务器应用程序移植到Windows中。纤程(fiber),相当与用户级别的线程或轻进程,纤程由Win32库函数支持,对核心是不可见的,纤程可以通过SwitchToFiber显示至另一合作纤程,以实现合作纤程之间的协同。
一、纤程的操作
线程是由Windows内核实现的,而纤程是以用户方式代码来实现的,内核并不可见(纤程采用非抢占的方式调度)。单线程可以包含一个或多个纤程。当使用纤程时,你必须执行的第一步操作是将现有的线程转换成一个纤程。
- 将线程转化为纤程
PVOID ConvertThreadToFiber (PVOID pvParam);
该函数为纤程的执行环境分配相应的内存。该执行环境由下列元素组成:
• 一个用户定义的值,它被初始化为传递给ConvertThreadToFiber的pvParam参数的值。
• 结构化异常处理链的头。
• 纤程内存栈的最高和最低地址(当将线程转换成纤程时,这也是线程的内存栈) 。
• CPU寄存器,包括堆栈指针、指令指针和其他。
当对纤程的执行环境进行分配和初始化后,就可以将执行环境的地址与线程关联起来。该线程被转换成一个纤程,而纤程则在该线程上运行。ConvertThreadToFiber函数实际上返回纤程的执行环境的内存地址。(自己不能对该执行环境的数据进行读写操作,必要时纤程函数会对该结构的内容进行操作)。
如果纤程(线程)返回或调用ExitThread函数,那么纤程和线程都会终止运行。
- 使多的纤程在同一个线程上运行
当前正在运行纤程的线程调用CreateFiber函数
PVOID CreateFiber( DWORD dwStackSize,
PFIBER_START_ROUTINE pfnStartAddress, PVOID pvParam);
首先,创建一个新内存栈,大小由dwStackSize指定(通常为0,按默认设置它创建一个内存栈,其大小可以扩展为 1 MB。如果设定一个非0值,那么就用设定的大小来保存和使用内存栈)。
接着,函数分配一个新的纤程执行环境结构并进行初始化。值为pvParam参数的值,新内存栈的最高和最低地址被保存,同时,纤程函数的内存地址(作为pfnStartAddress参数来传递)也被保存。函数返回纤程运行环境的内存地址。这个新纤程并不执行,因为当前运行的纤程仍然在执行。
pfnStartAddress参数用于设定必须实现的纤程例程的地址,它必须采用下面的原型:
VOID WINAPI FiberFunc(PVOID pvParam);
当纤程被初次调度时,该函数就开始运行,并且将原先传递给 CreateFiber的pvParam的值传递给它。可以在这个纤程函数中执行想执行的任何操作。每次只能运行一个纤程。
3、运行纤程:
VOID SwitchToFiber(PVOID pvFiberExecutionContext);
pvFiberExecutionContext是调用CreateFiber或ConvertThreadToFiber时返回的纤程的执行环境的内存地址。该内存地址告诉该函数要对哪个纤程进行调度。内部执行下列操作步骤:
1)将某些当前CPU寄存器保存在当前运行的纤程执行环境中,包括指令指针寄存器和堆栈指针寄存器
2)将上次保存在即将运行的纤程执行环境中的寄存器装入CPU寄存器。这些寄存器包括堆栈指针寄存器。这样,当线程继续执行时,就可以使用该纤程的内存栈。
3) 它将纤程的执行环境与线程关联起来,线程运行特定的纤程。
4) 将线程的指令指针设置为已保存的指令指针。线程(纤程)从该纤程上次执行的地方开始继续执行。
SwitchToFiber函数是纤程获得C P U时间的唯一途径。必须在相应的时间显式调用该函数,可以对纤程的调度可以实施全面的控制。
- 删除纤程:
VOID DeleteFiber(PVOID pvFiberExecutionContext);
pvFiberExecutionContext是纤程执行环境的地址(传递当前与线程相关联的纤程地址,就在内部调用 ExitThread,该线程及其创建的所有纤程全部被撤消)。通常由一个纤程调用,以便删除另一个纤程。
- 获得纤程执行环境:
PVOID GetCurrentFiber();
PVOID GetFiberData();