前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Windows内核原理-同步IO与异步IO

Windows内核原理-同步IO与异步IO

原创
作者头像
用户6786055
修改于 2019-12-16 10:22:13
修改于 2019-12-16 10:22:13
1.9K0
举报
文章被收录于专栏:杰哥技术分享杰哥技术分享

背景

在前段时间检查异常连接导致的内存泄漏排查的过程中,主要涉及到了windows异步I/O相关的知识,看了许多包括重叠I/O、完成端口、IRP、设备驱动程序等Windows下I/O相关的知识,虽然学习到了很多东西,但是仍然需要自顶而下的将所有知识进行梳理。

目的

本片文章主要讲解同步I/O与异步I/O相关知识,希望通过编写本篇文章为起点,对windows内核原理知识进行学习与梳理。发现并弥补遗漏的知识点并加以学习。同时通过理解windows内核原理,设计出更好、更合理的应用程序。

I/O

I/O即输入输出。在现在操作系统,输入输出是计算机完整功能必不可少的一部分。处理器负责各种计算任务,然后通过各种输入输出设备与外界进行交互。常见的输入输出设备包括键盘、鼠标、显示器、硬盘、网络适配器接口等。有了硬件设备,在软件层面上,使得操作系统通过以一致的方式与设备驱动交互从而的操控硬件设备。而应用程序通过统一的接口与系统内核进行交互。

Windows从一开始就设计了可扩展的I/O接口。在应用层通过统一的Win32 API,将I/O请求分配给正确的设备驱动程序。设备驱动程序调用设备控制器来操控硬件。而内核通过硬件抽象层与硬件进行交互。硬件抽象层提供了供内核和驱动调用的例程

例程就是系统提供的API或服务。

在Windows下分为内核模式和用户模式。应用程序运行在用户模式下,操作系统和驱动程序运行在内核模式下。应用程序通过调用Win32 API与Windows内核交互。

20190820191937.png
20190820191937.png

Windows内核则通过设备驱动程序与设备控制器进行通讯,而设备控制器则直接操控硬件设备。

设备驱动程序分为即插即用驱动程序、内核扩展驱动程序和文件系统驱动程序。其中文件系统驱动程序用于接收I/O请求,然后将请求转换为真正的存储设备或网络设备的I/O请求。

20190820191133.png
20190820191133.png

设备控制器可以通过内存映射I/O的方式将设备的内存与主存映射,通过内存映射I/O后,处理器访问的就不是主存而是设备控制器的寄存器内存。但是这种方式的访问效率并不高,不适合大数据量I/O读写。通常硬盘和网络驱动器采用直接访问内存(DMA)的方式进行大量数据的I/O操作。DMA需要硬件支持,硬件会有DMA控制器,在硬件执行I/O操作的时候,不会占用CPU的指令周期,DMA控制器会和设备进行I/O操作。当数据传输完成后,DMA则会通知处理器I/O操作完成。

20190820191613.png
20190820191613.png

同步I/O

当我们要把文件从硬盘读取到内存时,硬盘的读取速度是远小于内存的写入速度的。因此当我们使用一个线程从硬盘读取文件到内存中时。通常需要等待硬盘将数据从硬盘读取到内存中,此时线程将被阻塞,但是不会消耗指令周期。当读取完毕时,线程继续执行后续操作。

虽然DMA执行的时候当前线程被阻塞,此时处理器可以获取另一个线程内核执行其他操作,由于线程是非常昂贵的资源,因此使用同步I/O的方式若需要并发执行时,需要大量的创建线程资源,这就产生了大量的线程上下文切换。

在大多数x86和x64的多处理器,线程上下文切换时间间隔大约为15ms。 CPU每过大约15ms将CPU寄存器当前的线程上下文存回到该线程的上下文,然后该线程不在运行。然后系统检查剩下的可调度线程内核对象,选择一个线程的内核对象,将其上下文载入导CPU寄存器中。 关于Windows线程相关内容可以查阅《Windows via C/C++ 第五版》的第七章

异步I/O

前面提到了当硬件进行I/O传输时,实际上通常使用DMA技术执行I/O操作,不会占用CPU的指令周期。因此只要操作系统支持异步I/O,则可以极大的提升系统性能,最大程度的降低线程数量,减少线程上下文切换产生的性能损失。

在Windows下的异步I/O我们也可以称之为重叠(overlapped)I/O。重叠的意思是执行I/O请求的时间与线程执行其他任务的时间是重叠的,即执行真正I/O请求的时候,我们的工作线程可以执行其他请求,而不会阻塞等待I/O请求执行完毕。

当使用一个线程向设备发出一个异步I/O请求时,该请求被传给设备驱动程序,设备驱动程序处理I/O请求时并不会等待I/O请求完成,而是将I/O请求加入到设备驱动程序的队列中,然后返回一个I/O处理中的信号。而实际的I/O操作则由设备驱动程序将I/O请求传给指定的硬件设备执行I/O操作。应用程序的线程并不需要挂起等待I/O请求的完成,从而可以继续执行其他任务。当某一时刻设备驱动程序完成了该I/O请求处理,设备控制器通过中断指令通知I/O请求完成,处理器则将通知I/O请求已完成。

I/O完成通知

在Windows中一共支持四种接收完成通知的方式。分别为触发设备内核对象、触发时间内核对象、可提醒I/O以及I/O完成端口。

触发设备内核

当设备驱动加载时会创建一个设备驱动对象,设备驱动程序还会为设备创建对应的设备对象。设备对象代表的是每一个物理设备或逻辑设备。设备对象描述了一个特定设备的状态信息,包括I/O请求的状态。在通过异步I/O将I/O请求添加到队列之前,会将设备内核对象设置为未触发,此时就可以使用该设备内核对象进行同步操作,当I/O请求完成后则会将设备内核对象设置为触发状态。使用设备内核对象进行线程同步时,无法区分当前完成通知的I/O是读操作还是写操作,因此无论是读还是写都会将其状态设置为触发状态。

事件内核对象

通过设备内核对象进行I/O通知由于无法区分读写操作,因此并没有什么用。通过事件内核对象我们可以将读写事件分离。在调用读写操作的时候会返回对应的读写事件内核对象。这样我们就可以等待对应的事件内核对象知道是什么I/O操作完成。我们可以通过等待多个事件内核对象,但是一次性最多只能等待64个事件内核对象,即一个线程最多只能创建64个事件内核对象进行等待。若需要监控上万个连接,则需要创建上百个线程进行监控。

可提醒I/O

在系统创建线程的时候会创建一个与线程相关的队列,该队列被称为异步调用(APC)队列,当发出一个I/O请求时,我们可以告诉设备驱动程序在调用线程的APC队列中添加一项完成函数,在I/O完成通知时调用完成函数进行回调。I/O完成通知最大的问题是,请求时哪个线程调用的,必须由哪个线程回调。它不支持负载均衡机制。

完成端口

I/O完成端口的设计理论依据是并发编程的线程数必须有一个上限,即最佳并发线程数为CPU的逻辑线程数。I/O完成端口充分的发挥了并发编程的优势的同时又避免了线程上下文切换带来的性能损失。

完成端口可能是最复杂的内核对现象,但是它又是Windows下性能最佳的I/O通知方式。

首先我们需要创建一个I/O完成端口,创建完成端口的时候可以指定线程数量。通过将设备与I/O完成端口进行关联。此使我们发出的I/O请求时,系统内核返回IO_PENDDING状态,然后线程就可以继续处理其他事情。而DMA继续执行I/O操作,将数据从设备读取到设备控制器的缓冲区中,并对其进行必要的校验后,将数据通过系统总线传输到内存中。当数据传输完成后,DMA发出中断指令通知数据传输完毕,系统则会通过前面创建的I/O线程将I/O完成请求加入到I/O完成队列中。

然后我们通过调用Win32 API就可以获取到对应的设备I/O完成请求通知,通知会将I/O完成请求从完成队列移除。

总结

  1. 同步I/O会阻塞线程,想要提高执行速度必须增加线程,但是会由于线程上下文切换造成性能损失。
  2. Windows下大约每15ms会进行一次线程调度。减少windows线程能降低内存占用(默认线程栈大小为1M),降低线程上下文切换造成的性能损失。
  3. Windows支持原生的异步I/O。异步I/O也可以称为重叠I/O。使用异步I/O时线程不会阻塞,系统底层将每个I/O请求生成I/O请求包(IRP)加入到设备驱动程序的请求队列中,然后直接返回IO_PENDDING状态表示请求受理成功,当底层设备完成了真实的I/O请求后会通过中断控制器通过中断操作通知CPU,CPU会调度一个线程通知上层设备驱动程序,将完成通知加入到完成队列中。此时上层应用即可获取到完成通知。
  4. 完成端口是windows下性能最佳的完成通知方式。它最大程度的减少线程上下文切换。
  5. 使用异步I/O和完成端口实现高性能I/O操作的主要原因有三点。一是减少I/O上下文切换;二是异步不阻塞线程,预先提供一个socket用于连接,而不是接受到时再创建socket(socket创建也是比较耗资源的);三是避免了内存复制。
  6. 如何减少线程,如何避免内存复制,如何提高线程利用率,避免线程阻塞。以上几点是所有高性能框架或高性能应用程序必备的条件。

参考文档

  1. cpu内存访问速度,磁盘和网络速度
  2. 手把手教你玩转SOCKET模型:完成端口(Completion Port)详解
  3. Reactor与Proactor的概念
  4. 如何深刻理解reactor和proactor?
  5. I/O Completion Ports
  6. 《Windows via C/C++ 第五版》
  7. 《Windows内核原理与实现》
  8. WaitForMultipleObjects用法详解,一看就懂

出处:https://www.cnblogs.com/Jack-Blog/p/11923838.html

作者:杰哥很忙

本文使用「CC BY 4.0」创作共享协议。欢迎转载,请在明显位置给出出处及链接。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
IOCP异步优化
2. IO操作: CPU会把内存中的程序委托给其他的网络、磁盘等驱动程序,让这些外部的驱动程序来进行具体的处理,处理完成以后再返回给内存程序。对于这两类操作的优化方式是不一样的。内存操作的特点是占用CPU资源,CPU不断的计算。对于内存密集型的操作(Compute-Bound Operation)的优化,我们可以把一个大任务拆分成多个互不影响的子任务,那么就能让多个CPU同时参与运算,最后合并子任务的结果,所花的时间自然就少了。所以内存密集型的操作(Compute-Bound Operation)的优化有一个前提:超线程、多核、甚至是真正的多个CPU的计算机能够同时运行多个线程,对于只有一个CPU的计算机不适合。多线程之间的状态切换是需要额外的CPU资源的。IO操作的特点是基本不占用CPU资源,但是它会占用当前的工作者线程,并使其进入等待状态,等待IO完成的处理结果,然后在继续执行。但是在ASP.NET这种天然多线程的环境里,CLR线程池容量是有上限的,这个上限也代表了应用程序最多可以同时执行的请求数量。如果我们CLR线程池的所有线程都进入了IO等待状态,当再有新用户进来,我们的服务就停止响应了。目前我们IO操作的缺点是当前工作者线程同步等待IO,任何IO处理都会霸占一条工作者线程。所以对于IO密集型的操作(IO-Bound Operation)的优化,我们的思路是使用IOCP(I/O Completion Port)。IOCP翻译了中文是IO完成端口,它是一种异步形态,原理是这样的:当前工作者线程在进行IO处理时,委托给某个设备驱动程序,然后自己返回线程池,当IO完成后,OS会通过IOCP提醒CLR它工作已经完成,当CLR接收到通知后,会唤醒一个I/O线程并且运行用户的回调。
小蜜蜂
2019/07/15
1.2K0
IOCP异步优化
高性能网络通讯原理
本来想对netty的源码进行学习和探究,但是在写netty之前许多底层的知识和原理性的东西理解清楚,那么对学习网络通讯框架的效果则会事半功倍。
用户6786055
2019/12/16
5740
完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三
----- By PiggyXP(小猪)
战神伽罗
2019/07/24
9382
探索计算机的I/O控制方式:了解DMA控制器的作用与优势
在前面我们已经了解到,每个设备都配备了一个设备控制器。当CPU向设备控制器发送命令并将其存储在寄存器中时,设备控制器会执行相应的操作。然而,尽管设备控制器会更新状态寄存器的状态,但是如何将这些信息传达给CPU呢?
努力的小雨
2023/11/21
7070
键盘敲入 A 字母时,操作系统期间发生了什么...
键盘可以说是我们最常使用的输入硬件设备了,但身为程序员的你,你知道「键盘敲入 A 字母时,操作系统期间发生了什么吗」?
小林coding
2020/08/25
6070
键盘敲入 A 字母时,操作系统期间发生了什么...
操作系统之设备管理一、I/O管理概述二、I/O硬件组成三、I/O控制方式(重点)四、I/O软件组成五、I/O相关技术六、I/O设备的管理七、I/O性能问题
一、I/O管理概述 1.1 计算机I/O系统结构 1.2 I/O管理示意图 1.3 I/O的特点 I/O性能经常称为系统性能的瓶颈 操作系统庞大复杂的原因之一:资源多、杂,并发,均来自I/O 速度
JavaEdge
2018/05/16
6.4K0
linux的输入输出
Intel采用双独立总线(英语:Dual Independent Bus,DIB),使用外部的前端总线到主系统存储器,和内部的后端总线于一个或多个中央处理器、CPU缓存间。CPU 里面的内存接口,直接和系统总线通信,然后系统总线再接入一个 I/O 桥接器(I/O Bridge)。这个 I/O 桥接器,一边接入了我们的内存总线,使得我们的 CPU 和内存通信;另一边呢,又接入了一个 I/O 总线,用来连接 I/O 设备。
没有故事的陈师傅
2021/07/21
3.9K0
计算机总述--工作原理
在操作系统中,CPU被抽象成了时间片,而后将程序抽象成进程,通过分配时间片让程序运行起来。CPU有寻址单元用于来识别变量在内存的中所保存的集体内存地址。
陈不成i
2021/05/25
6440
键盘鼠标磁盘设备管理
电脑可以外接很多设备,如键盘、鼠标、硬盘、显示器、网卡等,每个设备的用法和功能不同,操作系统为了对这些输入输出设备进行统一管理,必须要屏蔽设备之间的差异,因此需要设备控制器。
shysh95
2021/11/09
7840
肝了很久!一文了解操作系统 I/O
我们之前的文章提到了操作系统的三个抽象,它们分别是进程、地址空间和文件,除此之外,操作系统还要控制所有的 I/O 设备。操作系统必须向设备发送命令,捕捉中断并处理错误。它还应该在设备和操作系统的其余部分之间提供一个简单易用的接口。操作系统如何管理 I/O 是我们接下来的重点。
cxuan
2020/06/28
1.2K0
肝了很久!一文了解操作系统 I/O
C# Windows异步I/O操作
关于Windows的异步I/O操作,只要解决的是同步I/O操作的线程利用率问题,通过异步I/O Api来提升线程的利用率,提升系统的吞吐能力,将各种I/O操作交给线程池然后交由硬件设备执行,期间完全不占用线程和CPU资源.
郑小超.
2019/05/25
8350
《CLR via C#》笔记:第5部分 线程处理(2)
本博客所总结书籍为《CLR via C#(第4版)》清华大学出版社,2021年11月第11次印刷(如果是旧版书籍或者pdf可能会出现书页对不上的情况) 你可以理解为本博客为该书的精简子集,给正在学习中的人提供一个“glance”,以及对于部分专业术语或知识点给出解释/博客链接。 【本博客有如下定义“Px x”,第一个代表书中的页数,第二个代表大致内容从本页第几段开始。(如果有last+x代表倒数第几段,last代表最后一段)】 电子书可以在博客首页的文档-资源归档中找到,或者点击:传送门自行查找。如有能力
[Sugar]
2022/09/21
1.2K0
设备驱动程序通知应用程序的几种方法
摘要 在目前流行的Windows操作系统中,设备驱动程序是操纵硬件的最底层软件接口。为了共享在设备驱动程序设计过程中的经验,给出设备驱动程序通知应用程序的5种方法,详细说明每种方法的原理和实现过程,并给出实现的部分核心代码。希望能够给设备驱动程序的设计者提供一些帮助。
战神伽罗
2019/11/04
1.9K0
.NET Core多线程 (2) 异步 - 上
举个例子,在高峰期去餐厅吃饭,会先排队拿个小票,然后去逛一下玩玩,等到排到时会被通知就餐,这时再回到餐厅就可以点餐了。
Edison Zhou
2023/08/09
3140
.NET Core多线程 (2) 异步 - 上
读鸿蒙论文,看性能优化
《 Microkernel Goes General: Performance and Compatibility in the HongMeng Production Microkernel》论文中提到的一些性能优化的思路和方法是很有学习价值的,结合论文里提到的点,我做了个视频。为了方便大家观看,我梳理了这个文字版本。
泊浮目
2024/11/07
1870
读鸿蒙论文,看性能优化
I/O中断原理
在Windows内核原理-同步IO与异步IO和《高性能网络通讯原理》两篇文章中,都出现了中断这两个字。本篇文章会对中断操作的原理进行说明。
用户6786055
2019/12/16
2K0
【RT-Thread笔记】IO设备模型及GPIO设备
应用程序通过 I/O 设备管理接口获得正确的设备驱动,然后通过这个设备驱动与底层 I/O 硬件设备进行数据(或控制)交互。
正念君
2019/11/28
1.4K0
【计算机基础】操作系统
是一组控制和管理计算机硬件和软件资源,合理对各类作业进行调度,以及方便用户使用的程序集合。
章鱼carl
2022/03/31
9560
【计算机基础】操作系统
c++ 网络编程(九)TCP/IP LINUX/windows--使用IOCP模型 多线程超详细教程 以及 多线程实现服务端
原文链接:https://www.cnblogs.com/DOMLX/p/9661012.html
徐飞机
2018/09/30
3.2K0
c++ 网络编程(九)TCP/IP LINUX/windows--使用IOCP模型      多线程超详细教程 以及 多线程实现服务端
聊聊运维应该了解的一些内核知识
本文主要是《Linux内核设计与实现》这本书的读书笔记,这本书我读了不下十遍,但依然感觉囫囵吞枣。我结合自己的理解,从这本书中整理出了一些运维应该了解的内核知识,希望对大家能够有所帮助。另外,推荐大家读下这边书,这本书主要讲内核设计、实现原理和方法,有利于理解内核的一些机理。
力哥聊运维与云计算
2019/11/28
1.2K0
推荐阅读
相关推荐
IOCP异步优化
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档