第十二章 纤程
使用纤程(fiber)
为了兼容UNIX服务器应用程序的移植。
使用纤程
线程是在内核模式下实现的,操作系统控制。
而纤程是在用户模式下实现的,内核对纤程一无所知。
一个线程可以包含一个或多个纤程。(内核仅能调度线程,而纤程由我们调度)
将一个已有的线程转换为纤程
WINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
ConvertThreadToFiber(
_In_opt_ LPVOID lpParameter
);
这个函数会为纤程分配一个CONTEXT包含
1)一个用户自定义的值,它被初始化为传给ConvertThreadToFiber的lpParameter参数的值
2)结构化异常处理链的头
3)纤程栈的顶部和底部的内存地址(当我们将一个线程转换为纤程的时候,这时候也是线程栈)
4)某些CPU寄存器,包括栈指针,指令指针以及其他寄存器
默认情况下x86系统中CPU的浮点状态信息不属于CPU寄存器的一部分,不会为每个纤程都维护一份,而如果纤程要执行浮点操作,那会导致数据被破坏。
为了覆盖系统的默认行为需要使用新的ConvertThreadToFiberEx函数
允许传入FIBER_FLAG_FLOAT_SWITCH标志:
WINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
ConvertThreadToFiberEx(
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwFlags
);
除非打算在一个线程中执行多个纤程否则将线程转换为纤程没有任何意义。
在当前线程中创建另一个纤程
WINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
CreateFiber(
_In_ SIZE_T dwStackSize,
_In_ LPFIBER_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter
);
如果要使用大量的纤程,希望纤程消耗更少的内存使用下列函数来创建纤程。
WINBASEAPI
_Ret_maybenull_
LPVOID
WINAPI
CreateFiberEx(
_In_ SIZE_T dwStackCommitSize,
_In_ SIZE_T dwStackReserveSize,
_In_ DWORD dwFlags,
_In_ LPFIBER_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter
);
dwStackCommitSize设置一开始要调拨的物理存储页。
dwStackReservesize 运行我们预定指定的虚拟内存。
dwFlags可以接受FIBER_FLAG_FLOAT_SWITCH将浮点运算状态保留
其他参数和CreateFiber相同
pfnStartAddress用来指定纤程函数的地址:
VOID WINAPI FiberFunc(PVOID pvParam);
但是CreateFiber创建的新纤程默认不会执行。(因为一个线程中只能执行一个纤程)
需要调用SwitchToFiber来切换纤程
WINBASEAP