• 异步I/O和非阻塞I/O(轮询)


    异步与非阻塞听起来似乎是一回事。从实际效果而言,两者都达到了我们并行I/O的目的。但从计算机内核I/O而言,异步/同步和阻塞/非阻塞实际上是两回事。

    操作系统内核对于I/O只有两种方式:阻塞与非阻塞。

    在调用阻塞I/O时,应用程序需要等待I/O完成才返回结果。阻塞I/O的一个特点是调用之后一定要等到系统内核层面完成所有操作后,调用才结束。以读取磁盘上的一段文件为例,系统内核在完成磁盘寻道、读取数据、复制数据到内存中之后,这个调用才结束。阻塞I/O造成CPU等待I/O,CPU的处理能力不能得到充分利用。为了提高性能,内核提供了非阻塞I/O。

    非阻塞I/O调用之后会立即返回。返回之后,CPU的时间片可以用来处理其他事务,此时的性能提升是明显的。

    但非阻塞I/O也存在一些问题,用于完整的I/O并没有完成,立即返回的并不是业务层期望的数据,而仅仅是当前调用的状态。为了获取完整的数据,应用程序需要重复调用I/O操作来确认是否完成。这种重复调用判断操作是否完成的技术叫做轮询

    任意技术都并非完美的。阻塞I/O造成CPU等待,非阻塞I/O带来的麻烦却是需要轮询去确认是否完全完成数据获取,它会让CPU处理状态判断,这是对CPU资源的浪费。

    下面完美看看轮询技术是如何演进以减小I/O状态判断的CPU损耗。

    现存的轮询技术主要有一下几种:

    1. read:

    最原始性能最低的一种,通过重复调用来检查I/O的状态以完成完整数据的读取。在得到最终数据前,CPU一直消耗在等待上。

    2. select:

    它是在read基础上改进的一种方案。通过对文件描述符上的事件状态来进行判断。

    select轮询具有一个较弱的限制,那就是由于它采用一个1024长度的数组来存储状态,所以它最多可以同时检查1024个文件描述符。

    3. poll:

    该方案较select方案有所改进,采用链表的方式避免数组长度的限制,其次它能避免不需要的检查。但是当文件描述符较多的时候,它的性能还是十分低下的。

    4. epoll:

    该方案是Linux下效率最高的I/O事件通知机制。在进入轮询的时候如果没有检查到I/O事件,将会进行休眠,直到事件发生将它唤醒。它是真实利用了事件通知、执行回调的方式,而不是遍历查询,所以不会浪费CPU,执行效率较高。

    5. kqueue:

    该方案的实现方式与epoll类似,不过它仅在FreeBSD系统中存在。

    轮询技术满足了非阻塞I/O确保获取完整数据的需求,但是对于应用程序而言,它仍然只能算是一种同步,因为应用程序仍然需要等待I/O完全返回,依旧会费了很多时间来等待。等待期间,CPU要么用于遍历文件描述符的状态,要么用于休眠等待事件发生。

  • 相关阅读:
    编程中Visual Studio常用的快捷键
    解决博易博客后台文章管理页面无法显示分页的问题
    iReaper for WP7 顺利完工
    Visual Studio中web应用程序和网站区别
    SQL批处理
    SQL安全性
    实习之路之篇
    python 日志文件
    后端调用python遥感功能的方式
    C#使用系统的“显示桌面”功能(Shell.Application)
  • 原文地址:https://www.cnblogs.com/i-hard-working/p/10393608.html
Copyright © 2020-2023  润新知