[笔记]Windows核心编程《十二》纤程

简介: Windows核心编程《十二》纤程

系列文章目录


[笔记]Windows核心编程《一》错误处理、字符编码

[笔记]Windows核心编程《二》内核对象

[笔记]Windows核心编程《三》进程

[笔记]Windows核心编程《四》作业

[笔记]快乐的LInux命令行《五》什么是shell

[笔记]Windows核心编程《五》线程基础

[笔记]Windows核心编程《六》线程调度、优先级和关联性

[笔记]Windows核心编程《七》用户模式下的线程同步

[笔记]Windows核心编程《八》用内核对象进行线程同步

[笔记]Windows核心编程《九》同步设备I/O和异步设备I/O

[笔记]Windows核心编程《十一》Windows线程池

[笔记]Windows核心编程《十二》纤程

[笔记]Windows核心编程《十三》windows内存体系结构

[笔记]Windows核心编程《十四》探索虚拟内存

[笔记]Windows核心编程《十五》在应用程序中使用虚拟内存

[笔记]Windows核心编程《十六》线程栈

[笔记]Windows核心编程《十七》内存映射文件

[笔记]Windows核心编程《十八》堆栈

[笔记]Windows核心编程《十九》DLL基础

[笔记]Windows核心编程《二十》DLL的高级操作技术

[笔记]Windows核心编程《二十一》线程本地存储器TLS

[笔记]Windows核心编程《二十二》注入DLL和拦截API

[笔记]Windows核心编程《二十三》结构化异常处理

文章目录


   系列文章目录

   前言

   使用纤程

       将一个已有的线程转换为一个纤程

           一个已有的线程转换为一个纤程

           在当前线程中创建另一个纤程

           需要调用SwitchToFiber来切换纤程

           调用DeleteFiber来销毁纤程

           获得纤程执行的上下文

           返回纤程的用户自定义值(CreateFiber所传递的pvParam)

   Counter示例程序

前言


目的:

为了更容易将已有的UNIX服务器应用迁移到Windows,增加了纤程。

UNIX应用程序的开发人员创建了线程包,来实现类似线程功能。

使用纤程


  • 线程在windows内核中实现的。
  • 纤程是在用户模式下实现的。
  • 内核仅能调度线程,而纤程由我们调度
  • 一个线程可包含多个纤程。

将一个已有的线程转换为一个纤程


一个已有的线程转换为一个纤程

PVOID ConvertThreadToFiber(PVOID pvParam);

如果函数成功,返回值是纤维的地址;如果函数失败,返回值是零。

这个函数为纤程的执行上下文CONTEXT分配内存。

执行上下文一般包含:

   一个用户自定义的值(pvParam)

   结构化异常处理链的头

   纤程栈的顶部和底部的内存地址

   某些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将浮点运算状态保留。

lpfnStartAddress:用来指定纤程函数的地址。例如以下就是定义一个纤程函数。

VOID WINAPI FiberFunc(PVOID pvParam);

其他参数和CreateFiber相同。

CreateFiber返回的是为纤程创建的CONTEXT的地址(和ConvertThreadToFiber类似)

但是CreateFiber创建的新纤程默认不会执行。(因为一个线程中只能执行一个纤程)

需要调用SwitchToFiber来切换纤程

WINBASEAPI
VOID
WINAPI
SwitchToFiber(
    _In_ LPVOID lpFiber
    );

lpFiber是用CreateFiber或ConvertThreadToFiber返回的值,告诉函数要调用哪个纤程。SwitchToFiber会执行以下步骤:

1)将一些cpu寄存器目前的值,其中包括指令指针(IP)寄存器和栈指针寄存器(SP) 保存在当前运行的纤程的CONTEXT中

2)从即将运行的纤程的执行CONTEXT中载入先前保存的寄存器值并载入cpu

这些寄存器中包含栈指针寄存器,这样单线程继续执行就会使用新纤程的栈。

3)将新纤程的执行CONTEXT和线程关联,让线程运行指定的纤程。

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

SwitchToFiber是让纤程得到cpu时间切片的唯一方法。所以纤程的调度完全由我们自己掌控。

调用DeleteFiber来销毁纤程

WINBASEAPI
VOID
WINAPI
DeleteFiber(
    _In_ LPVOID lpFiber
    );

lpFiber是纤程的CONTEXT地址。该函数会删除参数所表示的纤程。如果线程和纤程绑定了,其内部会调用ExitThread同时销毁当前的线程。

(TerminateThread不会销毁线程栈)

将转成了纤程的线程转回来。

ConvertTiberToThread(Ex)

如果为纤程保存一些信息可以使用纤程局部存储区(Fiber Local Storage, FLS)函数

其他纤程相关的函数

获得纤程执行的上下文

PVOID GetCurrentFiber();

返回纤程的用户自定义值(CreateFiber所传递的pvParam)

PVOID GetFiberData();

Counter示例程序


相关:

参考1

参考2

相关文章
|
1月前
|
监控 Ubuntu Linux
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
这篇文章介绍了如何在Ubuntu和Windows系统中通过设置相同的时区并使用ntp服务来解决时间同步问题。
65 4
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
|
2月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
2月前
|
Windows
[原创]用MASM32编程获取windows类型
[原创]用MASM32编程获取windows类型
|
2月前
|
JavaScript 前端开发 API
MASM32编程通过WMI获取Windows计划任务
MASM32编程通过WMI获取Windows计划任务
|
2月前
|
API Windows
MASM32编程获取Windows当前桌面主题名
MASM32编程获取Windows当前桌面主题名
|
3月前
|
编译器 开发工具 C语言
解锁QtCreator跨界神技!Windows下轻松驾驭OpenCV动态库,让你的跨平台开发如虎添翼,秒变视觉编程大师!
【8月更文挑战第4天】QtCreator是一款强大的跨平台IDE,便于创建多平台应用。本教程教你如何在Windows环境下集成OpenCV库至Qt项目。首先,下载匹配MinGW的OpenCV预编译版并解压。接着,在QtCreator中新建或打开项目,并在.pro文件中添加OpenCV的头文件和库文件路径。确保编译器设置正确。随后编写测试代码,例如加载和显示图片,并进行编译运行。完成这些步骤后,你就能在QtCreator中利用OpenCV进行图像处理开发了。
226 6
|
3月前
|
数据库 Windows
超详细步骤解析:从零开始,手把手教你使用 Visual Studio 打造你的第一个 Windows Forms 应用程序,菜鸟也能轻松上手的编程入门指南来了!
【8月更文挑战第31天】创建你的第一个Windows Forms (WinForms) 应用程序是一个激动人心的过程,尤其适合编程新手。本指南将带你逐步完成一个简单WinForms 应用的开发。首先,在Visual Studio 中创建一个“Windows Forms App (.NET)”项目,命名为“我的第一个WinForms 应用”。接着,在空白窗体中添加一个按钮和一个标签控件,并设置按钮文本为“点击我”。然后,为按钮添加点击事件处理程序`button1_Click`,实现点击按钮后更新标签文本为“你好,你刚刚点击了按钮!”。
273 0
|
4月前
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
127 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
4月前
|
存储 安全 数据安全/隐私保护
Windows 32 汇编笔记(一):基础知识
Windows 32 汇编笔记(一):基础知识
|
3月前
|
存储 编译器 Linux
Windows 32 汇编笔记(二):使用 MASM
Windows 32 汇编笔记(二):使用 MASM
下一篇
无影云桌面