目录

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

    • 背景
    • 目的
    • I/O
      • 同步I/O
      • 异步I/O
      • I/O完成通知
    • 总结
    • 参考文档

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


背景

在前段时间检查异常连接导致的内存泄漏排查的过程中,主要涉及到了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内核交互。

Windows内核则通过设备驱动程序与设备控制器进行通讯,而设备控制器则直接操控硬件设备。
设备驱动程序分为即插即用驱动程序、内核扩展驱动程序和文件系统驱动程序。其中文件系统驱动程序用于接收I/O请求,然后将请求转换为真正的存储设备或网络设备的I/O请求。

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

同步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/11385686.html
作者博客:杰哥很忙
欢迎转载,请在明显位置给出出处及链接

转载于:https://www.cnblogs.com/Jack-Blog/p/11385686.html

Windows内核原理-同步IO与异步IO相关推荐

  1. Reactor模型和Proactor模型:同步IO与异步IO

    Table of Contents 服务端的线程模型 2种fd 3种事件 Reactor模型-同步I/O 1.单Reactor单线程模型 2.单Reactor多线程模型 3.主从Reactor多线程模 ...

  2. 【网络编程】同步IO、异步IO、阻塞IO、非阻塞IO

    IO分两阶段: 1.数据准备阶段:在该阶段,根据是否等待数据准备,将IO分成阻塞和非阻塞: 2.内核空间复制回用户进程缓冲区阶段:在该阶段,只要程序需要等待复制完成,才能往下运行(尽管这个时间很短), ...

  3. 【多线程】0.理解一下5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    5种IO模型.阻塞IO和非阻塞IO.同步IO和异步IO 看了一些文章,发现有很多不同的理解,可能是因为大家入切的角度.环境不一样.所以,我们先说明基本的IO操作及环境. 本文是在<UNIX网络编 ...

  4. 同步IO、异步IO、阻塞IO、非阻塞IO、复用IO

    参考:同步IO 异步IO 作者:今天天气眞好 发布时间: 2021-04-19 09:42:29 网址:https://blog.csdn.net/qq_51118175/article/detail ...

  5. 程序员成长之旅——同步IO和异步IO(五种IO模型)

    程序员成长之旅--同步IO和异步IO(五种IO模型) 同步和异步 同步 异步 消息通知 场景比喻 阻塞和非阻塞 阻塞 非阻塞 事例 同步IO 阻塞IO 非阻塞IO 信号驱动IO 多路转接IO 异步IO ...

  6. 同步IO(阻塞IO、非阻塞IO), 异步IO的理解

    什么是IO? 在计算机中无时无刻不存在着对数据的访问和读取(数据都存储在物理的媒介上,例如寄存器,高速缓存,内存,磁盘,网卡等等),这些操作被称为IO. 阻塞IO 当用户线程发起IO请求后,会进行系统 ...

  7. 简述同步IO、异步IO、阻塞IO、非阻塞IO之间的联系与区别

    POSIX 同步IO.异步IO.阻塞IO.非阻塞IO,这几个词常见于各种各样的与网络相关的文章之中,往往不同上下文中它们的意思是不一样的,以致于我在很长一段时间对此感到困惑,所以想写一篇文章整理一下. ...

  8. 5种IO模型、阻塞IO和非阻塞IO、同步IO和异步IO

    5种IO模型.阻塞IO和非阻塞IO.同步IO和异步IO 看了一些文章,发现有很多不同的理解,可能是因为大家入切的角度.环境不一样.所以,我们先说明基本的IO操作及环境.本文是在<UNIX网络编程 ...

  9. 重叠IO模型-异步IO

    重叠IO模型-异步IO http://laiba.tianya.cn/laiba/CommMsgs?cmm=959&tid=2701316824681802728 说到重叠模型首先还是提一下异 ...

最新文章

  1. ROC(receiver operating characteristic curve)曲线与ROC分析
  2. 【SHARE】WEB前端学习资料
  3. C/C++之函数返回值为指针或者是引用时常见错误总结
  4. mybatis中因为不理解$与#而出现的bug
  5. php 模拟客户端访问,PHP通过伪造和模拟客户端COOKIE登陆来采集抓取远程网址
  6. java数组随机数不重复_java产生不重复随机数
  7. LR:Code-29723 Error: Failed to deliver a p2p message from parent to child process, reason。。。
  8. 第二次 HDOJ 1003
  9. 大神总结的一套PCB学习方法! 真得很受用!
  10. 分贝测试软件哪个好 家庭影院,家庭影院5.1和7.1哪种好?5.1和7.1家庭影院区别...
  11. oracle14 jar的pom,MyEclipse环境下如何采用Maven导入ojdbc14.jar和ojdbc6.jar | 贝壳里的海...
  12. C语言回调函数详解及实例
  13. 微服务架构设计思维导图总结
  14. 第九十二章 SQL函数 LPAD
  15. Mysql第二章习题
  16. python实现3d人物建模_一张图实现3D人脸建模!这是中科院博士生入选ECCV的新研究 | 开源...
  17. dede常用标签(随时更新)
  18. DR和DIS的区别?
  19. 哪种一致性哈希算法才是解决分布式缓存问题的王者?
  20. 亚马逊Amazon-API接口使用说明

热门文章

  1. Applese 涂颜色(欧拉定理降幂+快速幂)
  2. 【宜搭客户说第二期】宜搭助力跨境金融行业实现数字化管理
  3. JavaScript中函数的种类
  4. 《明日方舟》的塔防元素:是鸡肋还是精髓?
  5. 从0开始搭建一个战棋游戏的AI(初级教程)
  6. TestBird成为“国家手游测试中心”
  7. 关于MyBatis框架这一篇就够了
  8. 利用超链接<a>标签的【href】与【onclick】的优先级做提示窗判断,降低删除误操作次数
  9. centos安装 TA-Lib
  10. ORA-01031 权限不足-过程中DBA 角色用户无法执行DDL